- millert@cvs.openbsd.org 2014/07/15 15:54:14
     [PROTOCOL auth-options.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c]
     [auth-rsa.c auth.c auth1.c auth2-hostbased.c auth2-kbdint.c auth2-none.c]
     [auth2-passwd.c auth2-pubkey.c auth2.c canohost.c channels.c channels.h]
     [clientloop.c misc.c misc.h monitor.c mux.c packet.c readconf.c]
     [readconf.h servconf.c servconf.h serverloop.c session.c ssh-agent.c]
     [ssh.c ssh_config.5 sshconnect.c sshconnect1.c sshconnect2.c sshd.c]
     [sshd_config.5 sshlogin.c]
     Add support for Unix domain socket forwarding.  A remote TCP port
     may be forwarded to a local Unix domain socket and vice versa or
     both ends may be a Unix domain socket.  This is a reimplementation
     of the streamlocal patches by William Ahern from:
         http://www.25thandclement.com/~william/projects/streamlocal.html
     OK djm@ markus@
diff --git a/clientloop.c b/clientloop.c
index 02510e2..397c965 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.260 2014/06/27 16:41:56 markus Exp $ */
+/* $OpenBSD: clientloop.c,v 1.261 2014/07/15 15:54:14 millert Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -100,13 +100,13 @@
 #include "cipher.h"
 #include "kex.h"
 #include "log.h"
+#include "misc.h"
 #include "readconf.h"
 #include "clientloop.h"
 #include "sshconnect.h"
 #include "authfd.h"
 #include "atomicio.h"
 #include "sshpty.h"
-#include "misc.h"
 #include "match.h"
 #include "msg.h"
 #include "roaming.h"
@@ -871,13 +871,11 @@
 process_cmdline(void)
 {
 	void (*handler)(int);
-	char *s, *cmd, *cancel_host;
-	int delete = 0, local = 0, remote = 0, dynamic = 0;
-	int cancel_port, ok;
-	Forward fwd;
+	char *s, *cmd;
+	int ok, delete = 0, local = 0, remote = 0, dynamic = 0;
+	struct Forward fwd;
 
 	memset(&fwd, 0, sizeof(fwd));
-	fwd.listen_host = fwd.connect_host = NULL;
 
 	leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
 	handler = signal(SIGINT, SIG_IGN);
@@ -943,29 +941,20 @@
 
 	/* XXX update list of forwards in options */
 	if (delete) {
-		cancel_port = 0;
-		cancel_host = hpdelim(&s);	/* may be NULL */
-		if (s != NULL) {
-			cancel_port = a2port(s);
-			cancel_host = cleanhostname(cancel_host);
-		} else {
-			cancel_port = a2port(cancel_host);
-			cancel_host = NULL;
-		}
-		if (cancel_port <= 0) {
-			logit("Bad forwarding close port");
+		/* We pass 1 for dynamicfwd to restrict to 1 or 2 fields. */
+		if (!parse_forward(&fwd, s, 1, 0)) {
+			logit("Bad forwarding close specification.");
 			goto out;
 		}
 		if (remote)
-			ok = channel_request_rforward_cancel(cancel_host,
-			    cancel_port) == 0;
+			ok = channel_request_rforward_cancel(&fwd) == 0;
 		else if (dynamic)
-                	ok = channel_cancel_lport_listener(cancel_host,
-			    cancel_port, 0, options.gateway_ports) > 0;
+			ok = channel_cancel_lport_listener(&fwd,
+			    0, &options.fwd_opts) > 0;
 		else
-                	ok = channel_cancel_lport_listener(cancel_host,
-			    cancel_port, CHANNEL_CANCEL_PORT_STATIC,
-			    options.gateway_ports) > 0;
+			ok = channel_cancel_lport_listener(&fwd,
+			    CHANNEL_CANCEL_PORT_STATIC,
+			    &options.fwd_opts) > 0;
 		if (!ok) {
 			logit("Unkown port forwarding.");
 			goto out;
@@ -977,16 +966,13 @@
 			goto out;
 		}
 		if (local || dynamic) {
-			if (!channel_setup_local_fwd_listener(fwd.listen_host,
-			    fwd.listen_port, fwd.connect_host,
-			    fwd.connect_port, options.gateway_ports)) {
+			if (!channel_setup_local_fwd_listener(&fwd,
+			    &options.fwd_opts)) {
 				logit("Port forwarding failed.");
 				goto out;
 			}
 		} else {
-			if (channel_request_remote_forwarding(fwd.listen_host,
-			    fwd.listen_port, fwd.connect_host,
-			    fwd.connect_port) < 0) {
+			if (channel_request_remote_forwarding(&fwd) < 0) {
 				logit("Port forwarding failed.");
 				goto out;
 			}
@@ -999,7 +985,9 @@
 	enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
 	free(cmd);
 	free(fwd.listen_host);
+	free(fwd.listen_path);
 	free(fwd.connect_host);
+	free(fwd.connect_path);
 }
 
 /* reasons to suppress output of an escape command in help output */
@@ -1845,9 +1833,8 @@
 	originator_port = packet_get_int();
 	packet_check_eom();
 
-	debug("client_request_forwarded_tcpip: listen %s port %d, "
-	    "originator %s port %d", listen_address, listen_port,
-	    originator_address, originator_port);
+	debug("%s: listen %s port %d, originator %s port %d", __func__,
+	    listen_address, listen_port, originator_address, originator_port);
 
 	c = channel_connect_by_listen_address(listen_address, listen_port,
 	    "forwarded-tcpip", originator_address);
@@ -1858,6 +1845,27 @@
 }
 
 static Channel *
+client_request_forwarded_streamlocal(const char *request_type, int rchan)
+{
+	Channel *c = NULL;
+	char *listen_path;
+
+	/* Get the remote path. */
+	listen_path = packet_get_string(NULL);
+	/* XXX: Skip reserved field for now. */
+	if (packet_get_string_ptr(NULL) == NULL)
+		fatal("%s: packet_get_string_ptr failed", __func__);
+	packet_check_eom();
+
+	debug("%s: %s", __func__, listen_path);
+
+	c = channel_connect_by_listen_path(listen_path,
+	    "forwarded-streamlocal@openssh.com", "forwarded-streamlocal");
+	free(listen_path);
+	return c;
+}
+
+static Channel *
 client_request_x11(const char *request_type, int rchan)
 {
 	Channel *c = NULL;
@@ -1984,6 +1992,8 @@
 
 	if (strcmp(ctype, "forwarded-tcpip") == 0) {
 		c = client_request_forwarded_tcpip(ctype, rchan);
+	} else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) {
+		c = client_request_forwarded_streamlocal(ctype, rchan);
 	} else if (strcmp(ctype, "x11") == 0) {
 		c = client_request_x11(ctype, rchan);
 	} else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {