mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
New Plink operating mode: 'plink -shareexists'.
A Plink invocation of the form 'plink -shareexists <session>' tests for a currently live connection-sharing upstream for the session in question. <session> can be any syntax you'd use with Plink to make the actual connection (a host/port number, a bare saved session name, -load, whatever). I envisage this being useful for things like adaptive proxying - e.g. if you want to connect to host A which you can't route to directly, and you might already have a connection to either of hosts B or C which are viable proxies, then you could write a proxy shell script which checks whether you already have an upstream for B or C and goes via whichever one is currently active. Testing for the upstream's existence has to be done by actually connecting to its socket, because on Unix the mere existence of a Unix-domain socket file doesn't guarantee that there's a process listening to it. So we make a test connection, and then immediately disconnect; hence, that shows up in the upstream's event log.
This commit is contained in:
parent
14892997d6
commit
7c2ea22784
3
putty.h
3
putty.h
@ -445,6 +445,9 @@ struct backend_tag {
|
||||
*/
|
||||
void (*unthrottle) (void *handle, int);
|
||||
int (*cfg_info) (void *handle);
|
||||
/* Only implemented in the SSH protocol: check whether a
|
||||
* connection-sharing upstream exists for a given configuration. */
|
||||
int (*test_for_upstream)(const char *host, int port, Conf *conf);
|
||||
const char *name;
|
||||
int protocol;
|
||||
int default_port;
|
||||
|
1
raw.c
1
raw.c
@ -339,6 +339,7 @@ Backend raw_backend = {
|
||||
raw_provide_logctx,
|
||||
raw_unthrottle,
|
||||
raw_cfg_info,
|
||||
NULL /* test_for_upstream */,
|
||||
"raw",
|
||||
PROT_RAW,
|
||||
0
|
||||
|
1
rlogin.c
1
rlogin.c
@ -425,6 +425,7 @@ Backend rlogin_backend = {
|
||||
rlogin_provide_logctx,
|
||||
rlogin_unthrottle,
|
||||
rlogin_cfg_info,
|
||||
NULL /* test_for_upstream */,
|
||||
"rlogin",
|
||||
PROT_RLOGIN,
|
||||
513
|
||||
|
14
ssh.c
14
ssh.c
@ -3586,6 +3586,19 @@ static void ssh_hostport_setup(const char *host, int port, Conf *conf,
|
||||
}
|
||||
}
|
||||
|
||||
static int ssh_test_for_upstream(const char *host, int port, Conf *conf)
|
||||
{
|
||||
char *savedhost;
|
||||
int savedport;
|
||||
int ret;
|
||||
|
||||
ssh_hostport_setup(host, port, conf, &savedhost, &savedport, NULL);
|
||||
ret = ssh_share_test_for_upstream(savedhost, savedport, conf);
|
||||
sfree(savedhost);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Connect to specified host and port.
|
||||
* Returns an error message, or NULL on success.
|
||||
@ -11645,6 +11658,7 @@ Backend ssh_backend = {
|
||||
ssh_provide_logctx,
|
||||
ssh_unthrottle,
|
||||
ssh_cfg_info,
|
||||
ssh_test_for_upstream,
|
||||
"ssh",
|
||||
PROT_SSH,
|
||||
22
|
||||
|
1
ssh.h
1
ssh.h
@ -24,6 +24,7 @@ void sshfwd_x11_is_local(struct ssh_channel *c);
|
||||
|
||||
extern Socket ssh_connection_sharing_init(const char *host, int port,
|
||||
Conf *conf, Ssh ssh, void **state);
|
||||
int ssh_share_test_for_upstream(const char *host, int port, Conf *conf);
|
||||
void share_got_pkt_from_server(void *ctx, int type,
|
||||
unsigned char *pkt, int pktlen);
|
||||
void share_activate(void *state, const char *server_verstring);
|
||||
|
49
sshshare.c
49
sshshare.c
@ -2027,6 +2027,55 @@ char *ssh_share_sockname(const char *host, int port, Conf *conf)
|
||||
return sockname;
|
||||
}
|
||||
|
||||
static void nullplug_socket_log(Plug plug, int type, SockAddr addr, int port,
|
||||
const char *error_msg, int error_code) {}
|
||||
static int nullplug_closing(Plug plug, const char *error_msg, int error_code,
|
||||
int calling_back) { return 0; }
|
||||
static int nullplug_receive(Plug plug, int urgent, char *data,
|
||||
int len) { return 0; }
|
||||
static void nullplug_sent(Plug plug, int bufsize) {}
|
||||
|
||||
int ssh_share_test_for_upstream(const char *host, int port, Conf *conf)
|
||||
{
|
||||
static const struct plug_function_table fn_table = {
|
||||
nullplug_socket_log,
|
||||
nullplug_closing,
|
||||
nullplug_receive,
|
||||
nullplug_sent,
|
||||
NULL
|
||||
};
|
||||
struct nullplug {
|
||||
const struct plug_function_table *fn;
|
||||
} np;
|
||||
|
||||
char *sockname, *logtext, *ds_err, *us_err;
|
||||
int result;
|
||||
Socket sock;
|
||||
|
||||
np.fn = &fn_table;
|
||||
|
||||
sockname = ssh_share_sockname(host, port, conf);
|
||||
|
||||
sock = NULL;
|
||||
logtext = ds_err = us_err = NULL;
|
||||
result = platform_ssh_share(sockname, conf, (Plug)&np, (Plug)NULL, &sock,
|
||||
&logtext, &ds_err, &us_err, FALSE, TRUE);
|
||||
|
||||
sfree(logtext);
|
||||
sfree(ds_err);
|
||||
sfree(us_err);
|
||||
sfree(sockname);
|
||||
|
||||
if (result == SHARE_NONE) {
|
||||
assert(sock == NULL);
|
||||
return FALSE;
|
||||
} else {
|
||||
assert(result == SHARE_DOWNSTREAM);
|
||||
sk_close(sock);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Init function for connection sharing. We either open a listening
|
||||
* socket and become an upstream, or connect to an existing one and
|
||||
|
1
telnet.c
1
telnet.c
@ -1129,6 +1129,7 @@ Backend telnet_backend = {
|
||||
telnet_provide_logctx,
|
||||
telnet_unthrottle,
|
||||
telnet_cfg_info,
|
||||
NULL /* test_for_upstream */,
|
||||
"telnet",
|
||||
PROT_TELNET,
|
||||
23
|
||||
|
@ -58,14 +58,14 @@ Backend null_backend = {
|
||||
null_init, null_free, null_reconfig, null_send, null_sendbuffer, null_size,
|
||||
null_special, null_get_specials, null_connected, null_exitcode, null_sendok,
|
||||
null_ldisc, null_provide_ldisc, null_provide_logctx, null_unthrottle,
|
||||
null_cfg_info, "null", -1, 0
|
||||
null_cfg_info, NULL /* test_for_upstream */, "null", -1, 0
|
||||
};
|
||||
|
||||
Backend loop_backend = {
|
||||
loop_init, loop_free, null_reconfig, loop_send, null_sendbuffer, null_size,
|
||||
null_special, null_get_specials, null_connected, null_exitcode, null_sendok,
|
||||
null_ldisc, null_provide_ldisc, null_provide_logctx, null_unthrottle,
|
||||
null_cfg_info, "loop", -1, 0
|
||||
null_cfg_info, NULL /* test_for_upstream */, "loop", -1, 0
|
||||
};
|
||||
|
||||
struct loop_state {
|
||||
|
@ -607,6 +607,7 @@ int main(int argc, char **argv)
|
||||
int errors;
|
||||
int use_subsystem = 0;
|
||||
int got_host = FALSE;
|
||||
int just_test_share_exists = FALSE;
|
||||
unsigned long now;
|
||||
struct winsize size;
|
||||
|
||||
@ -685,6 +686,8 @@ int main(int argc, char **argv)
|
||||
--argc;
|
||||
provide_xrm_string(*++argv);
|
||||
}
|
||||
} else if (!strcmp(p, "-shareexists")) {
|
||||
just_test_share_exists = TRUE;
|
||||
} else {
|
||||
fprintf(stderr, "plink: unknown option \"%s\"\n", p);
|
||||
errors = 1;
|
||||
@ -959,6 +962,19 @@ int main(int argc, char **argv)
|
||||
!conf_get_str_nthstrkey(conf, CONF_portfwd, 0))
|
||||
conf_set_int(conf, CONF_ssh_simple, TRUE);
|
||||
|
||||
if (just_test_share_exists) {
|
||||
if (!back->test_for_upstream) {
|
||||
fprintf(stderr, "Connection sharing not supported for connection "
|
||||
"type '%s'\n", back->name);
|
||||
return 1;
|
||||
}
|
||||
if (back->test_for_upstream(conf_get_str(conf, CONF_host),
|
||||
conf_get_int(conf, CONF_port), conf))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start up the connection.
|
||||
*/
|
||||
|
@ -1218,6 +1218,7 @@ Backend pty_backend = {
|
||||
pty_provide_logctx,
|
||||
pty_unthrottle,
|
||||
pty_cfg_info,
|
||||
NULL /* test_for_upstream */,
|
||||
"pty",
|
||||
-1,
|
||||
0
|
||||
|
@ -591,6 +591,7 @@ Backend serial_backend = {
|
||||
serial_provide_logctx,
|
||||
serial_unthrottle,
|
||||
serial_cfg_info,
|
||||
NULL /* test_for_upstream */,
|
||||
"serial",
|
||||
PROT_SERIAL,
|
||||
0
|
||||
|
@ -303,6 +303,7 @@ int main(int argc, char **argv)
|
||||
int errors;
|
||||
int got_host = FALSE;
|
||||
int use_subsystem = 0;
|
||||
int just_test_share_exists = FALSE;
|
||||
unsigned long now, next, then;
|
||||
|
||||
sklist = NULL;
|
||||
@ -364,6 +365,8 @@ int main(int argc, char **argv)
|
||||
} else if (!strcmp(p, "-pgpfp")) {
|
||||
pgp_fingerprints();
|
||||
exit(1);
|
||||
} else if (!strcmp(p, "-shareexists")) {
|
||||
just_test_share_exists = TRUE;
|
||||
} else {
|
||||
fprintf(stderr, "plink: unknown option \"%s\"\n", p);
|
||||
errors = 1;
|
||||
@ -596,6 +599,19 @@ int main(int argc, char **argv)
|
||||
logctx = log_init(NULL, conf);
|
||||
console_provide_logctx(logctx);
|
||||
|
||||
if (just_test_share_exists) {
|
||||
if (!back->test_for_upstream) {
|
||||
fprintf(stderr, "Connection sharing not supported for connection "
|
||||
"type '%s'\n", back->name);
|
||||
return 1;
|
||||
}
|
||||
if (back->test_for_upstream(conf_get_str(conf, CONF_host),
|
||||
conf_get_int(conf, CONF_port), conf))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start up the connection.
|
||||
*/
|
||||
|
@ -453,6 +453,7 @@ Backend serial_backend = {
|
||||
serial_provide_logctx,
|
||||
serial_unthrottle,
|
||||
serial_cfg_info,
|
||||
NULL /* test_for_upstream */,
|
||||
"serial",
|
||||
PROT_SERIAL,
|
||||
0
|
||||
|
Loading…
Reference in New Issue
Block a user