1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +00:00

Server prep: factor out portfwd_raw_new().

This new function contains the core setup for a PortForwarding
structure, and should be reusable for any kind of forwarding that will
simply be passing data between a local socket and an SSH channel
without any tricky modifications. On the server side, X11 and agent
forwarding both work exactly like this, so they will find this
refactored function useful during setup.

The contents of the function was originally part of pfl_accepting,
which now does all that by calling the new function. pfl_accepting is
not _quite_ doing a simple unmodified forwarding, because it might
have to prefix it with a SOCKS exchange; in that situation it rewrites
a few fields of the PortForwarding to some less generic values once
portfwd_raw_new() has returned.
This commit is contained in:
Simon Tatham 2018-10-20 22:47:49 +01:00
parent 82661b7bf2
commit 8343961705

View File

@ -467,18 +467,10 @@ static const struct ChannelVtable PortForwarding_channelvt = {
chan_no_request_response,
};
/*
called when someone connects to the local port
*/
static int pfl_accepting(Plug *p, accept_fn_t constructor, accept_ctx_t ctx)
Channel *portfwd_raw_new(ConnectionLayer *cl, Plug **plug)
{
struct PortForwarding *pf;
struct PortListener *pl;
Socket *s;
const char *err;
pl = container_of(p, struct PortListener, plug);
pf = new_portfwd_state();
pf->plug.vt = &PortForwarding_plugvt;
pf->chan.initial_fixed_window_size = 0;
@ -486,29 +478,72 @@ static int pfl_accepting(Plug *p, accept_fn_t constructor, accept_ctx_t ctx)
pf->input_wanted = TRUE;
pf->c = NULL;
pf->cl = pl->cl;
pf->s = s = constructor(ctx, &pf->plug);
if ((err = sk_socket_error(s)) != NULL) {
free_portfwd_state(pf);
return err != NULL;
}
pf->cl = cl;
pf->input_wanted = TRUE;
pf->ready = 0;
pf->socks_state = SOCKS_NONE;
pf->hostname = NULL;
pf->port = 0;
*plug = &pf->plug;
return &pf->chan;
}
void portfwd_raw_free(Channel *pfchan)
{
struct PortForwarding *pf;
assert(pfchan->vt == &PortForwarding_channelvt);
pf = container_of(pfchan, struct PortForwarding, chan);
free_portfwd_state(pf);
}
void portfwd_raw_setup(Channel *pfchan, Socket *s, SshChannel *sc)
{
struct PortForwarding *pf;
assert(pfchan->vt == &PortForwarding_channelvt);
pf = container_of(pfchan, struct PortForwarding, chan);
pf->s = s;
pf->c = sc;
}
/*
called when someone connects to the local port
*/
static int pfl_accepting(Plug *p, accept_fn_t constructor, accept_ctx_t ctx)
{
struct PortListener *pl = container_of(p, struct PortListener, plug);
struct PortForwarding *pf;
Channel *chan;
Plug *plug;
Socket *s;
const char *err;
chan = portfwd_raw_new(pl->cl, &plug);
s = constructor(ctx, plug);
if ((err = sk_socket_error(s)) != NULL) {
portfwd_raw_free(chan);
return TRUE;
}
pf = container_of(chan, struct PortForwarding, chan);
if (pl->is_dynamic) {
pf->s = s;
pf->socks_state = SOCKS_INITIAL;
pf->socksbuf = strbuf_new();
pf->socksbuf_consumed = 0;
pf->port = 0; /* "hostname" buffer is so far empty */
sk_set_frozen(s, 0); /* we want to receive SOCKS _now_! */
} else {
pf->socks_state = SOCKS_NONE;
pf->hostname = dupstr(pl->hostname);
pf->port = pl->port;
pf->c = wrap_lportfwd_open(pl->cl, pf->hostname, pf->port,
s, &pf->chan);
portfwd_raw_setup(
chan, s,
wrap_lportfwd_open(pl->cl, pf->hostname, pf->port, s, &pf->chan));
}
return 0;