'ControlMaster persist'

David Woodhouse dwmw2 at infradead.org
Mon Jun 13 00:16:47 EST 2005


On Sun, 2005-06-12 at 14:18 +0100, David Woodhouse wrote:
> I'll do that in the next patch, which will add 'persist' and
> 'autopersist' to the available options.

... which start a master and leave it running even after the ssh command
which triggers its creation has gone. Looks like the simplest way to
achieve this is to fork a new ssh client process to become the master,
then wait for it to complete and use it in slave mode.

Should I make 'ask' and 'auto' into separate flags rather than
variations of the 'ControlMaster' option?

--- openssh-4.1p1/readconf.c~	2005-06-12 11:18:05.000000000 +0100
+++ openssh-4.1p1/readconf.c	2005-06-12 14:34:26.000000000 +0100
@@ -799,15 +799,19 @@
 			    filename, linenum);
 		value = 0;	/* To avoid compiler warning... */
 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
-			value = 1;
+			value = CONTROL_MASTER;
 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
-			value = 0;
+			value = CONTROL_SLAVE;
 		else if (strcmp(arg, "ask") == 0)
-			value = 2;
+			value = CONTROL_ASK;
+		else if (strcmp(arg, "persist") == 0)
+			value = CONTROL_PERSIST;
 		else if (strcmp(arg, "auto") == 0)
-			value = 3;
+			value = CONTROL_AUTO;
 		else if (strcmp(arg, "autoask") == 0)
-			value = 4;
+			value = CONTROL_AUTOASK;
+		else if (strcmp(arg, "autopersist") == 0)
+			value = CONTROL_AUTOPERSIST;
 		else
 			fatal("%.200s line %d: Bad ControlMaster argument.", filename, linenum);
 		if (*activep && *intptr == -1)
--- openssh-4.1p1/readconf.h~	2005-03-01 10:47:37.000000000 +0000
+++ openssh-4.1p1/readconf.h	2005-06-12 14:34:15.000000000 +0100
@@ -116,6 +116,13 @@
 	int	hash_known_hosts;
 }       Options;
 
+#define CONTROL_SLAVE		0
+#define CONTROL_MASTER		1
+#define CONTROL_ASK		2
+#define CONTROL_PERSIST		3
+#define CONTROL_AUTO		4
+#define CONTROL_AUTOASK		5
+#define CONTROL_AUTOPERSIST	6
 
 void     initialize_options(Options *);
 void     fill_default_options(Options *);
--- openssh-4.1p1/ssh.c~	2005-06-12 13:55:32.000000000 +0100
+++ openssh-4.1p1/ssh.c	2005-06-12 15:02:09.000000000 +0100
@@ -659,12 +659,52 @@
 			options.control_path = xstrdup(buffer_ptr(&path));
 		}
 	}
+ startpersist:
+	if (options.control_master == CONTROL_PERSIST) {
+		pid_t masterpid = fork();
+
+		if (masterpid < 0)
+			fatal("fork: %s", strerror(errno));
+
+		if (masterpid) {
+			/* We are the parent. Wait for the child to
+			   set itself up as master, then use its
+			   control socket */
+			int status;
+			if (waitpid(masterpid, &status, 0) < 0)
+				fatal("waitpid: %s", strerror(errno));
+
+			if (WIFEXITED(status)) {
+				if (WEXITSTATUS(status))
+					fatal("Master connection failed, returned %d", WEXITSTATUS(status));
+			} else if (WIFSIGNALED(status)) {
+				fatal("Master connection failed, died with signal %d", WTERMSIG(status));
+			} else {
+				fatal("Master connection failed. status %d\n", status);
+			}
+			/* The master exited with zero status, so the socket
+			   should be ready for us now */
+			options.control_master = CONTROL_SLAVE;
+		} else {
+			/* We are the child. Set ourselves up as master */
+			no_shell_flag = 1;
+			no_tty_flag = 1;
+			tty_flag = 0;
+			fork_after_authentication_flag = 1;
+			stdin_null_flag = 1;
+			options.control_master = CONTROL_MASTER;
+		}
+	}
+
 	if (options.control_path != NULL && 
-	    (options.control_master == 0 || options.control_master == 3 ||
-	     options.control_master == 4)) {
+	    (options.control_master == CONTROL_SLAVE || 
+	     options.control_master >= CONTROL_AUTO)) {
 		/* This only returns in the 'ask' cases, if we should
 		   become a master */
 		control_client(options.control_path);
+
+		if (options.control_master == CONTROL_PERSIST)
+			goto startpersist;
 	}
 
 	/* Open a connection to the remote host. */
@@ -1355,10 +1395,10 @@
 		fatal("%s socket(): %s", __func__, strerror(errno));
 
 	if (connect(sock, (struct sockaddr*)&addr, addr_len) == -1) {
-		if (options.control_master >= 2) {
+		if (options.control_master >= CONTROL_AUTO) {
 			debug("Couldn't connect to %s: %s", path, strerror(errno));
 			/* Automatic mode; return and become a master */
-			options.control_master -= 2;
+			options.control_master -= CONTROL_AUTO-1;
 			close(sock);
 			return;
 		}


-- 
dwmw2




More information about the openssh-unix-dev mailing list