Modernise the Socket/Plug vtable system.

Now I've got FROMFIELD, I can rework it so that structures providing
an implementation of the Socket or Plug trait no longer have to have
the vtable pointer as the very first thing in the structure. In
particular, this means that the ProxySocket structure can now directly
implement _both_ the Socket and Plug traits, which is always
_logically_ how it's worked, but previously it had to be implemented
via two separate structs linked to each other.
This commit is contained in:
Simon Tatham 2018-05-27 09:29:33 +01:00
Родитель 0fc2d3b455
Коммит 5129c40bea
24 изменённых файлов: 675 добавлений и 734 удалений

Просмотреть файл

@ -42,7 +42,7 @@ void proxy_socks5_offerencryptedauth(BinarySink *bs)
put_byte(bs, 0x03); /* CHAP */
}
int proxy_socks5_handlechap (Proxy_Socket p)
int proxy_socks5_handlechap (ProxySocket *p)
{
/* CHAP authentication reply format:
@ -158,7 +158,7 @@ int proxy_socks5_handlechap (Proxy_Socket p)
return 0;
}
int proxy_socks5_selectchap(Proxy_Socket p)
int proxy_socks5_selectchap(ProxySocket *p)
{
char *username = conf_get_str(p->conf, CONF_proxy_username);
char *password = conf_get_str(p->conf, CONF_proxy_password);

14
defs.h
Просмотреть файл

@ -36,6 +36,20 @@ typedef uint32_t uint32;
typedef struct BinarySink BinarySink;
typedef struct SockAddr_tag *SockAddr;
typedef struct Socket_vtable Socket_vtable;
typedef struct Plug_vtable Plug_vtable;
/* Note indirection: for historical reasons (it used to be closer to
* the OS socket type), the type that most code uses for a socket is
* 'Socket', not 'Socket *'. So an implementation of Socket or Plug
* has a 'const Socket *' field for the vtable pointer, and the
* 'Socket' type returned to client code is a pointer to _that_ in
* turn. */
typedef const Socket_vtable **Socket;
typedef const Plug_vtable **Plug;
/* Do a compile-time type-check of 'to_check' (without evaluating it),
* as a side effect of returning the value 'to_return'. Note that
* although this macro double-*expands* to_return, it always

Просмотреть файл

@ -10,37 +10,34 @@
#include "putty.h"
#include "network.h"
typedef struct Socket_error_tag *Error_Socket;
struct Socket_error_tag {
const struct socket_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
typedef struct {
char *error;
Plug plug;
};
const Socket_vtable *sockvt;
} ErrorSocket;
static Plug sk_error_plug(Socket s, Plug p)
{
Error_Socket ps = (Error_Socket) s;
Plug ret = ps->plug;
ErrorSocket *es = FROMFIELD(s, ErrorSocket, sockvt);
Plug ret = es->plug;
if (p)
ps->plug = p;
es->plug = p;
return ret;
}
static void sk_error_close(Socket s)
{
Error_Socket ps = (Error_Socket) s;
ErrorSocket *es = FROMFIELD(s, ErrorSocket, sockvt);
sfree(ps->error);
sfree(ps);
sfree(es->error);
sfree(es);
}
static const char *sk_error_socket_error(Socket s)
{
Error_Socket ps = (Error_Socket) s;
return ps->error;
ErrorSocket *es = FROMFIELD(s, ErrorSocket, sockvt);
return es->error;
}
static char *sk_error_peer_info(Socket s)
@ -48,26 +45,23 @@ static char *sk_error_peer_info(Socket s)
return NULL;
}
static const Socket_vtable ErrorSocket_sockvt = {
sk_error_plug,
sk_error_close,
NULL /* write */,
NULL /* write_oob */,
NULL /* write_eof */,
NULL /* flush */,
NULL /* set_frozen */,
sk_error_socket_error,
sk_error_peer_info,
};
Socket new_error_socket(const char *errmsg, Plug plug)
{
static const struct socket_function_table socket_fn_table = {
sk_error_plug,
sk_error_close,
NULL /* write */,
NULL /* write_oob */,
NULL /* write_eof */,
NULL /* flush */,
NULL /* set_frozen */,
sk_error_socket_error,
sk_error_peer_info,
};
Error_Socket ret;
ret = snew(struct Socket_error_tag);
ret->fn = &socket_fn_table;
ret->plug = plug;
ret->error = dupstr(errmsg);
return (Socket) ret;
ErrorSocket *es = snew(ErrorSocket);
es->sockvt = &ErrorSocket_sockvt;
es->plug = plug;
es->error = dupstr(errmsg);
return &es->sockvt;
}

Просмотреть файл

@ -15,12 +15,7 @@
#include "defs.h"
typedef struct SockAddr_tag *SockAddr;
/* pay attention to levels of indirection */
typedef struct socket_function_table **Socket;
typedef struct plug_function_table **Plug;
struct socket_function_table {
struct Socket_vtable {
Plug(*plug) (Socket s, Plug p);
/* use a different plug (return the old one) */
/* if p is NULL, it doesn't change the plug */
@ -39,7 +34,7 @@ struct socket_function_table {
typedef union { void *p; int i; } accept_ctx_t;
typedef Socket (*accept_fn_t)(accept_ctx_t ctx, Plug plug);
struct plug_function_table {
struct Plug_vtable {
void (*log)(Plug p, int type, SockAddr addr, int port,
const char *error_msg, int error_code);
/*

Просмотреть файл

@ -18,7 +18,7 @@ void proxy_socks5_offerencryptedauth(BinarySink *bs)
/* For telnet, don't add any new encrypted authentication routines */
}
int proxy_socks5_handlechap (Proxy_Socket p)
int proxy_socks5_handlechap (ProxySocket *p)
{
plug_closing(p->plug, "Proxy error: Trying to handle a SOCKS5 CHAP request"
@ -27,7 +27,7 @@ int proxy_socks5_handlechap (Proxy_Socket p)
return 1;
}
int proxy_socks5_selectchap(Proxy_Socket p)
int proxy_socks5_selectchap(ProxySocket *p)
{
plug_closing(p->plug, "Proxy error: Trying to handle a SOCKS5 CHAP request"
" in telnet-only build",

Просмотреть файл

@ -863,9 +863,6 @@ int pageant_delete_ssh2_key(struct ssh2_userkey *skey)
} while (0)
struct pageant_conn_state {
const struct plug_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
Socket connsock;
void *logctx;
pageant_logfn_t logfn;
@ -873,12 +870,15 @@ struct pageant_conn_state {
unsigned len, got;
int real_packet;
int crLine; /* for coroutine in pageant_conn_receive */
const Plug_vtable *plugvt;
};
static void pageant_conn_closing(Plug plug, const char *error_msg,
int error_code, int calling_back)
{
struct pageant_conn_state *pc = (struct pageant_conn_state *)plug;
struct pageant_conn_state *pc = FROMFIELD(
plug, struct pageant_conn_state, plugvt);
if (error_msg)
plog(pc->logctx, pc->logfn, "%p: error: %s", pc, error_msg);
else
@ -889,7 +889,8 @@ static void pageant_conn_closing(Plug plug, const char *error_msg,
static void pageant_conn_sent(Plug plug, int bufsize)
{
/* struct pageant_conn_state *pc = (struct pageant_conn_state *)plug; */
/* struct pageant_conn_state *pc = FROMFIELD(
plug, struct pageant_conn_state, plugvt); */
/*
* We do nothing here, because we expect that there won't be a
@ -910,7 +911,8 @@ static void pageant_conn_log(void *logctx, const char *fmt, va_list ap)
static void pageant_conn_receive(Plug plug, int urgent, char *data, int len)
{
struct pageant_conn_state *pc = (struct pageant_conn_state *)plug;
struct pageant_conn_state *pc = FROMFIELD(
plug, struct pageant_conn_state, plugvt);
char c;
crBegin(pc->crLine);
@ -959,46 +961,48 @@ static void pageant_conn_receive(Plug plug, int urgent, char *data, int len)
}
struct pageant_listen_state {
const struct plug_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
Socket listensock;
void *logctx;
pageant_logfn_t logfn;
const Plug_vtable *plugvt;
};
static void pageant_listen_closing(Plug plug, const char *error_msg,
int error_code, int calling_back)
{
struct pageant_listen_state *pl = (struct pageant_listen_state *)plug;
struct pageant_listen_state *pl = FROMFIELD(
plug, struct pageant_listen_state, plugvt);
if (error_msg)
plog(pl->logctx, pl->logfn, "listening socket: error: %s", error_msg);
sk_close(pl->listensock);
pl->listensock = NULL;
}
static const Plug_vtable pageant_connection_plugvt = {
NULL, /* no log function, because that's for outgoing connections */
pageant_conn_closing,
pageant_conn_receive,
pageant_conn_sent,
NULL /* no accepting function, because we've already done it */
};
static int pageant_listen_accepting(Plug plug,
accept_fn_t constructor, accept_ctx_t ctx)
{
static const struct plug_function_table connection_fn_table = {
NULL, /* no log function, because that's for outgoing connections */
pageant_conn_closing,
pageant_conn_receive,
pageant_conn_sent,
NULL /* no accepting function, because we've already done it */
};
struct pageant_listen_state *pl = (struct pageant_listen_state *)plug;
struct pageant_listen_state *pl = FROMFIELD(
plug, struct pageant_listen_state, plugvt);
struct pageant_conn_state *pc;
const char *err;
char *peerinfo;
pc = snew(struct pageant_conn_state);
pc->fn = &connection_fn_table;
pc->plugvt = &pageant_connection_plugvt;
pc->logfn = pl->logfn;
pc->logctx = pl->logctx;
pc->crLine = 0;
pc->connsock = constructor(ctx, (Plug) pc);
pc->connsock = constructor(ctx, &pc->plugvt);
if ((err = sk_socket_error(pc->connsock)) != NULL) {
sk_close(pc->connsock);
sfree(pc);
@ -1018,21 +1022,22 @@ static int pageant_listen_accepting(Plug plug,
return 0;
}
struct pageant_listen_state *pageant_listener_new(void)
{
static const struct plug_function_table listener_fn_table = {
NULL, /* no log function, because that's for outgoing connections */
pageant_listen_closing,
NULL, /* no receive function on a listening socket */
NULL, /* no sent function on a listening socket */
pageant_listen_accepting
};
static const Plug_vtable pageant_listener_plugvt = {
NULL, /* no log function, because that's for outgoing connections */
pageant_listen_closing,
NULL, /* no receive function on a listening socket */
NULL, /* no sent function on a listening socket */
pageant_listen_accepting
};
struct pageant_listen_state *pageant_listener_new(Plug *plug)
{
struct pageant_listen_state *pl = snew(struct pageant_listen_state);
pl->fn = &listener_fn_table;
pl->plugvt = &pageant_listener_plugvt;
pl->logctx = NULL;
pl->logfn = NULL;
pl->listensock = NULL;
*plug = &pl->plugvt;
return pl;
}

Просмотреть файл

@ -79,13 +79,13 @@ void keylist_update(void);
/*
* Functions to establish a listening socket speaking the SSH agent
* protocol. Call pageant_listener_new() to set up a state; then
* create a socket using the returned pointer as a Plug; then call
* create a socket using the returned Plug; then call
* pageant_listener_got_socket() to give the listening state its own
* socket pointer. Also, provide a logging function later if you want
* to.
*/
struct pageant_listen_state;
struct pageant_listen_state *pageant_listener_new(void);
struct pageant_listen_state *pageant_listener_new(Plug *plug);
void pageant_listener_got_socket(struct pageant_listen_state *pl, Socket sock);
void pageant_listener_set_logfn(struct pageant_listen_state *pl,
void *logctx, pageant_logfn_t logfn);

Просмотреть файл

@ -9,8 +9,6 @@
#include "ssh.h"
struct PortForwarding {
const struct plug_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
struct ssh_channel *c; /* channel structure held by ssh.c */
void *backhandle; /* instance of SSH backend itself */
/* Note that backhandle need not be filled in if c is non-NULL */
@ -43,11 +41,11 @@ struct PortForwarding {
*/
void *buffer;
int buflen;
const Plug_vtable *plugvt;
};
struct PortListener {
const struct plug_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
void *backhandle; /* instance of SSH backend itself */
Socket s;
/*
@ -61,6 +59,8 @@ struct PortListener {
*/
char *hostname;
int port;
const Plug_vtable *plugvt;
};
static struct PortForwarding *new_portfwd_state(void)
@ -113,7 +113,7 @@ static void pfl_log(Plug plug, int type, SockAddr addr, int port,
static void pfd_closing(Plug plug, const char *error_msg, int error_code,
int calling_back)
{
struct PortForwarding *pf = (struct PortForwarding *) plug;
struct PortForwarding *pf = FROMFIELD(plug, struct PortForwarding, plugvt);
if (error_msg) {
/*
@ -164,7 +164,7 @@ static void wrap_send_port_open(void *channel, const char *hostname, int port,
static void pfd_receive(Plug plug, int urgent, char *data, int len)
{
struct PortForwarding *pf = (struct PortForwarding *) plug;
struct PortForwarding *pf = FROMFIELD(plug, struct PortForwarding, plugvt);
if (pf->dynamic) {
while (len--) {
if (pf->sockslen >= pf->sockssize) {
@ -400,12 +400,20 @@ static void pfd_receive(Plug plug, int urgent, char *data, int len)
static void pfd_sent(Plug plug, int bufsize)
{
struct PortForwarding *pf = (struct PortForwarding *) plug;
struct PortForwarding *pf = FROMFIELD(plug, struct PortForwarding, plugvt);
if (pf->c)
sshfwd_unthrottle(pf->c, bufsize);
}
static const Plug_vtable PortForwarding_plugvt = {
pfd_log,
pfd_closing,
pfd_receive,
pfd_sent,
NULL
};
/*
* Called when receiving a PORT OPEN from the server to make a
* connection to a destination host.
@ -416,14 +424,6 @@ static void pfd_sent(Plug plug, int bufsize)
char *pfd_connect(struct PortForwarding **pf_ret, char *hostname,int port,
void *c, Conf *conf, int addressfamily)
{
static const struct plug_function_table fn_table = {
pfd_log,
pfd_closing,
pfd_receive,
pfd_sent,
NULL
};
SockAddr addr;
const char *err;
char *dummy_realhost = NULL;
@ -445,7 +445,7 @@ char *pfd_connect(struct PortForwarding **pf_ret, char *hostname,int port,
* Open socket.
*/
pf = *pf_ret = new_portfwd_state();
pf->fn = &fn_table;
pf->plugvt = &PortForwarding_plugvt;
pf->throttled = pf->throttle_override = 0;
pf->ready = 1;
pf->c = c;
@ -453,7 +453,7 @@ char *pfd_connect(struct PortForwarding **pf_ret, char *hostname,int port,
pf->dynamic = 0;
pf->s = new_connection(addr, dummy_realhost, port,
0, 1, 0, 0, (Plug) pf, conf);
0, 1, 0, 0, &pf->plugvt, conf);
sfree(dummy_realhost);
if ((err = sk_socket_error(pf->s)) != NULL) {
char *err_ret = dupstr(err);
@ -472,26 +472,19 @@ char *pfd_connect(struct PortForwarding **pf_ret, char *hostname,int port,
static int pfl_accepting(Plug p, accept_fn_t constructor, accept_ctx_t ctx)
{
static const struct plug_function_table fn_table = {
pfd_log,
pfd_closing,
pfd_receive,
pfd_sent,
NULL
};
struct PortForwarding *pf;
struct PortListener *pl;
Socket s;
const char *err;
pl = (struct PortListener *)p;
pl = FROMFIELD(p, struct PortListener, plugvt);
pf = new_portfwd_state();
pf->fn = &fn_table;
pf->plugvt = &PortForwarding_plugvt;
pf->c = NULL;
pf->backhandle = pl->backhandle;
pf->s = s = constructor(ctx, (Plug) pf);
pf->s = s = constructor(ctx, &pf->plugvt);
if ((err = sk_socket_error(s)) != NULL) {
free_portfwd_state(pf);
return err != NULL;
@ -522,6 +515,13 @@ static int pfl_accepting(Plug p, accept_fn_t constructor, accept_ctx_t ctx)
return 0;
}
static const Plug_vtable PortListener_plugvt = {
pfl_log,
pfl_closing,
NULL, /* recv */
NULL, /* send */
pfl_accepting
};
/*
* Add a new port-forwarding listener from srcaddr:port -> desthost:destport.
@ -533,14 +533,6 @@ char *pfl_listen(char *desthost, int destport, char *srcaddr,
int port, void *backhandle, Conf *conf,
struct PortListener **pl_ret, int address_family)
{
static const struct plug_function_table fn_table = {
pfl_log,
pfl_closing,
NULL, /* recv */
NULL, /* send */
pfl_accepting
};
const char *err;
struct PortListener *pl;
@ -548,7 +540,7 @@ char *pfl_listen(char *desthost, int destport, char *srcaddr,
* Open socket.
*/
pl = *pl_ret = new_portlistener_state();
pl->fn = &fn_table;
pl->plugvt = &PortListener_plugvt;
if (desthost) {
pl->hostname = dupstr(desthost);
pl->port = destport;
@ -557,7 +549,7 @@ char *pfl_listen(char *desthost, int destport, char *srcaddr,
pl->dynamic = 1;
pl->backhandle = backhandle;
pl->s = new_listener(srcaddr, port, (Plug) pl,
pl->s = new_listener(srcaddr, port, &pl->plugvt,
!conf_get_int(conf, CONF_lport_acceptall),
conf, address_family);
if ((err = sk_socket_error(pl->s)) != NULL) {

108
proxy.c
Просмотреть файл

@ -23,7 +23,7 @@
* Call this when proxy negotiation is complete, so that this
* socket can begin working normally.
*/
void proxy_activate (Proxy_Socket p)
void proxy_activate (ProxySocket *p)
{
void *data;
int len;
@ -73,14 +73,14 @@ void proxy_activate (Proxy_Socket p)
* unfreezing the actual underlying socket.
*/
if (!p->freeze)
sk_set_frozen((Socket)p, 0);
sk_set_frozen(&p->sockvt, 0);
}
/* basic proxy socket functions */
static Plug sk_proxy_plug (Socket s, Plug p)
{
Proxy_Socket ps = (Proxy_Socket) s;
ProxySocket *ps = FROMFIELD(s, ProxySocket, sockvt);
Plug ret = ps->plug;
if (p)
ps->plug = p;
@ -89,7 +89,7 @@ static Plug sk_proxy_plug (Socket s, Plug p)
static void sk_proxy_close (Socket s)
{
Proxy_Socket ps = (Proxy_Socket) s;
ProxySocket *ps = FROMFIELD(s, ProxySocket, sockvt);
sk_close(ps->sub_socket);
sk_addr_free(ps->remote_addr);
@ -98,7 +98,7 @@ static void sk_proxy_close (Socket s)
static int sk_proxy_write (Socket s, const void *data, int len)
{
Proxy_Socket ps = (Proxy_Socket) s;
ProxySocket *ps = FROMFIELD(s, ProxySocket, sockvt);
if (ps->state != PROXY_STATE_ACTIVE) {
bufchain_add(&ps->pending_output_data, data, len);
@ -109,7 +109,7 @@ static int sk_proxy_write (Socket s, const void *data, int len)
static int sk_proxy_write_oob (Socket s, const void *data, int len)
{
Proxy_Socket ps = (Proxy_Socket) s;
ProxySocket *ps = FROMFIELD(s, ProxySocket, sockvt);
if (ps->state != PROXY_STATE_ACTIVE) {
bufchain_clear(&ps->pending_output_data);
@ -122,7 +122,7 @@ static int sk_proxy_write_oob (Socket s, const void *data, int len)
static void sk_proxy_write_eof (Socket s)
{
Proxy_Socket ps = (Proxy_Socket) s;
ProxySocket *ps = FROMFIELD(s, ProxySocket, sockvt);
if (ps->state != PROXY_STATE_ACTIVE) {
ps->pending_eof = 1;
@ -133,7 +133,7 @@ static void sk_proxy_write_eof (Socket s)
static void sk_proxy_flush (Socket s)
{
Proxy_Socket ps = (Proxy_Socket) s;
ProxySocket *ps = FROMFIELD(s, ProxySocket, sockvt);
if (ps->state != PROXY_STATE_ACTIVE) {
ps->pending_flush = 1;
@ -144,7 +144,7 @@ static void sk_proxy_flush (Socket s)
static void sk_proxy_set_frozen (Socket s, int is_frozen)
{
Proxy_Socket ps = (Proxy_Socket) s;
ProxySocket *ps = FROMFIELD(s, ProxySocket, sockvt);
if (ps->state != PROXY_STATE_ACTIVE) {
ps->freeze = is_frozen;
@ -183,7 +183,7 @@ static void sk_proxy_set_frozen (Socket s, int is_frozen)
static const char * sk_proxy_socket_error (Socket s)
{
Proxy_Socket ps = (Proxy_Socket) s;
ProxySocket *ps = FROMFIELD(s, ProxySocket, sockvt);
if (ps->error != NULL || ps->sub_socket == NULL) {
return ps->error;
}
@ -195,8 +195,7 @@ static const char * sk_proxy_socket_error (Socket s)
static void plug_proxy_log(Plug plug, int type, SockAddr addr, int port,
const char *error_msg, int error_code)
{
Proxy_Plug pp = (Proxy_Plug) plug;
Proxy_Socket ps = pp->proxy_socket;
ProxySocket *ps = FROMFIELD(plug, ProxySocket, plugvt);
plug_log(ps->plug, type, addr, port, error_msg, error_code);
}
@ -204,8 +203,7 @@ static void plug_proxy_log(Plug plug, int type, SockAddr addr, int port,
static void plug_proxy_closing (Plug p, const char *error_msg,
int error_code, int calling_back)
{
Proxy_Plug pp = (Proxy_Plug) p;
Proxy_Socket ps = pp->proxy_socket;
ProxySocket *ps = FROMFIELD(p, ProxySocket, plugvt);
if (ps->state != PROXY_STATE_ACTIVE) {
ps->closing_error_msg = error_msg;
@ -219,8 +217,7 @@ static void plug_proxy_closing (Plug p, const char *error_msg,
static void plug_proxy_receive (Plug p, int urgent, char *data, int len)
{
Proxy_Plug pp = (Proxy_Plug) p;
Proxy_Socket ps = pp->proxy_socket;
ProxySocket *ps = FROMFIELD(p, ProxySocket, plugvt);
if (ps->state != PROXY_STATE_ACTIVE) {
/* we will lose the urgentness of this data, but since most,
@ -239,8 +236,7 @@ static void plug_proxy_receive (Plug p, int urgent, char *data, int len)
static void plug_proxy_sent (Plug p, int bufsize)
{
Proxy_Plug pp = (Proxy_Plug) p;
Proxy_Socket ps = pp->proxy_socket;
ProxySocket *ps = FROMFIELD(p, ProxySocket, plugvt);
if (ps->state != PROXY_STATE_ACTIVE) {
ps->sent_bufsize = bufsize;
@ -253,8 +249,7 @@ static void plug_proxy_sent (Plug p, int bufsize)
static int plug_proxy_accepting(Plug p,
accept_fn_t constructor, accept_ctx_t ctx)
{
Proxy_Plug pp = (Proxy_Plug) p;
Proxy_Socket ps = pp->proxy_socket;
ProxySocket *ps = FROMFIELD(p, ProxySocket, plugvt);
if (ps->state != PROXY_STATE_ACTIVE) {
ps->accepting_constructor = constructor;
@ -401,36 +396,35 @@ SockAddr name_lookup(const char *host, int port, char **canonicalname,
}
}
static const struct Socket_vtable ProxySocket_sockvt = {
sk_proxy_plug,
sk_proxy_close,
sk_proxy_write,
sk_proxy_write_oob,
sk_proxy_write_eof,
sk_proxy_flush,
sk_proxy_set_frozen,
sk_proxy_socket_error,
NULL, /* peer_info */
};
static const struct Plug_vtable ProxySocket_plugvt = {
plug_proxy_log,
plug_proxy_closing,
plug_proxy_receive,
plug_proxy_sent,
plug_proxy_accepting
};
Socket new_connection(SockAddr addr, const char *hostname,
int port, int privport,
int oobinline, int nodelay, int keepalive,
Plug plug, Conf *conf)
{
static const struct socket_function_table socket_fn_table = {
sk_proxy_plug,
sk_proxy_close,
sk_proxy_write,
sk_proxy_write_oob,
sk_proxy_write_eof,
sk_proxy_flush,
sk_proxy_set_frozen,
sk_proxy_socket_error,
NULL, /* peer_info */
};
static const struct plug_function_table plug_fn_table = {
plug_proxy_log,
plug_proxy_closing,
plug_proxy_receive,
plug_proxy_sent,
plug_proxy_accepting
};
if (conf_get_int(conf, CONF_proxy_type) != PROXY_NONE &&
proxy_for_destination(addr, hostname, port, conf))
{
Proxy_Socket ret;
Proxy_Plug pplug;
ProxySocket *ret;
SockAddr proxy_addr;
char *proxy_canonical_name;
const char *proxy_type;
@ -443,8 +437,9 @@ Socket new_connection(SockAddr addr, const char *hostname,
NULL)
return sret;
ret = snew(struct Socket_proxy_tag);
ret->fn = &socket_fn_table;
ret = snew(ProxySocket);
ret->sockvt = &ProxySocket_sockvt;
ret->plugvt = &ProxySocket_plugvt;
ret->conf = conf_copy(conf);
ret->plug = plug;
ret->remote_addr = addr; /* will need to be freed on close */
@ -478,7 +473,7 @@ Socket new_connection(SockAddr addr, const char *hostname,
proxy_type = "Telnet";
} else {
ret->error = "Proxy error: Unknown proxy method";
return (Socket) ret;
return &ret->sockvt;
}
{
@ -491,12 +486,6 @@ Socket new_connection(SockAddr addr, const char *hostname,
sfree(logmsg);
}
/* create the proxy plug to map calls from the actual
* socket into our proxy socket layer */
pplug = snew(struct Plug_proxy_tag);
pplug->fn = &plug_fn_table;
pplug->proxy_socket = ret;
{
char *logmsg = dns_log_msg(conf_get_str(conf, CONF_proxy_host),
conf_get_int(conf, CONF_addressfamily),
@ -511,9 +500,8 @@ Socket new_connection(SockAddr addr, const char *hostname,
conf_get_int(conf, CONF_addressfamily));
if (sk_addr_error(proxy_addr) != NULL) {
ret->error = "Proxy error: Unable to resolve proxy host name";
sfree(pplug);
sk_addr_free(proxy_addr);
return (Socket)ret;
return &ret->sockvt;
}
sfree(proxy_canonical_name);
@ -533,15 +521,15 @@ Socket new_connection(SockAddr addr, const char *hostname,
ret->sub_socket = sk_new(proxy_addr,
conf_get_int(conf, CONF_proxy_port),
privport, oobinline,
nodelay, keepalive, (Plug) pplug);
nodelay, keepalive, &ret->plugvt);
if (sk_socket_error(ret->sub_socket) != NULL)
return (Socket) ret;
return &ret->sockvt;
/* start the proxy negotiation process... */
sk_set_frozen(ret->sub_socket, 0);
ret->negotiate(ret, PROXY_CHANGE_NEW);
return (Socket) ret;
return &ret->sockvt;
}
/* no proxy, so just return the direct socket */
@ -596,7 +584,7 @@ static int get_line_end (char * data, int len)
return -1;
}
int proxy_http_negotiate (Proxy_Socket p, int change)
int proxy_http_negotiate (ProxySocket *p, int change)
{
if (p->state == PROXY_STATE_NEW) {
/* we are just beginning the proxy negotiate process,
@ -781,7 +769,7 @@ int proxy_http_negotiate (Proxy_Socket p, int change)
*/
/* SOCKS version 4 */
int proxy_socks4_negotiate (Proxy_Socket p, int change)
int proxy_socks4_negotiate (ProxySocket *p, int change)
{
if (p->state == PROXY_CHANGE_NEW) {
@ -932,7 +920,7 @@ int proxy_socks4_negotiate (Proxy_Socket p, int change)
}
/* SOCKS version 5 */
int proxy_socks5_negotiate (Proxy_Socket p, int change)
int proxy_socks5_negotiate (ProxySocket *p, int change)
{
if (p->state == PROXY_CHANGE_NEW) {
@ -1508,7 +1496,7 @@ char *format_telnet_command(SockAddr addr, int port, Conf *conf)
#undef ENSURE
}
int proxy_telnet_negotiate (Proxy_Socket p, int change)
int proxy_telnet_negotiate (ProxySocket *p, int change)
{
if (p->state == PROXY_CHANGE_NEW) {
char *formatted_cmd;

36
proxy.h
Просмотреть файл

@ -13,12 +13,9 @@
#define PROXY_ERROR_GENERAL 8000
#define PROXY_ERROR_UNEXPECTED 8001
typedef struct Socket_proxy_tag * Proxy_Socket;
struct Socket_proxy_tag {
const struct socket_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
typedef struct ProxySocket ProxySocket;
struct ProxySocket {
const char *error;
Socket sub_socket;
@ -58,7 +55,7 @@ struct Socket_proxy_tag {
* and further the proxy negotiation process.
*/
int (*negotiate) (Proxy_Socket /* this */, int /* change type */);
int (*negotiate) (ProxySocket * /* this */, int /* change type */);
/* current arguments of plug handlers
* (for use by proxy's negotiate function)
@ -89,24 +86,17 @@ struct Socket_proxy_tag {
int chap_num_attributes_processed;
int chap_current_attribute;
int chap_current_datalen;
const Socket_vtable *sockvt;
const Plug_vtable *plugvt;
};
typedef struct Plug_proxy_tag * Proxy_Plug;
extern void proxy_activate (ProxySocket *);
struct Plug_proxy_tag {
const struct plug_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
Proxy_Socket proxy_socket;
};
extern void proxy_activate (Proxy_Socket);
extern int proxy_http_negotiate (Proxy_Socket, int);
extern int proxy_telnet_negotiate (Proxy_Socket, int);
extern int proxy_socks4_negotiate (Proxy_Socket, int);
extern int proxy_socks5_negotiate (Proxy_Socket, int);
extern int proxy_http_negotiate (ProxySocket *, int);
extern int proxy_telnet_negotiate (ProxySocket *, int);
extern int proxy_socks4_negotiate (ProxySocket *, int);
extern int proxy_socks5_negotiate (ProxySocket *, int);
/*
* This may be reused by local-command proxies on individual
@ -119,7 +109,7 @@ char *format_telnet_command(SockAddr addr, int port, Conf *conf);
* whether encrypted proxy authentication is available.
*/
extern void proxy_socks5_offerencryptedauth(BinarySink *);
extern int proxy_socks5_handlechap (Proxy_Socket p);
extern int proxy_socks5_selectchap(Proxy_Socket p);
extern int proxy_socks5_handlechap (ProxySocket *);
extern int proxy_socks5_selectchap(ProxySocket *);
#endif

30
raw.c
Просмотреть файл

@ -11,9 +11,6 @@
#define RAW_MAX_BACKLOG 4096
typedef struct raw_backend_data {
const struct plug_function_table *fn;
/* the above field _must_ be first in the structure */
Socket s;
int closed_on_socket_error;
int bufsize;
@ -21,6 +18,8 @@ typedef struct raw_backend_data {
int sent_console_eof, sent_socket_eof, session_started;
Conf *conf;
const Plug_vtable *plugvt;
} *Raw;
static void raw_size(void *handle, int width, int height);
@ -34,7 +33,7 @@ static void c_write(Raw raw, const void *buf, int len)
static void raw_log(Plug plug, int type, SockAddr addr, int port,
const char *error_msg, int error_code)
{
Raw raw = (Raw) plug;
Raw raw = FROMFIELD(plug, struct raw_backend_data, plugvt);
backend_socket_log(raw->frontend, type, addr, port,
error_msg, error_code, raw->conf, raw->session_started);
}
@ -57,7 +56,7 @@ static void raw_check_close(Raw raw)
static void raw_closing(Plug plug, const char *error_msg, int error_code,
int calling_back)
{
Raw raw = (Raw) plug;
Raw raw = FROMFIELD(plug, struct raw_backend_data, plugvt);
if (error_msg) {
/* A socket error has occurred. */
@ -89,7 +88,7 @@ static void raw_closing(Plug plug, const char *error_msg, int error_code,
static void raw_receive(Plug plug, int urgent, char *data, int len)
{
Raw raw = (Raw) plug;
Raw raw = FROMFIELD(plug, struct raw_backend_data, plugvt);
c_write(raw, data, len);
/* We count 'session start', for proxy logging purposes, as being
* when data is received from the network and printed. */
@ -98,10 +97,17 @@ static void raw_receive(Plug plug, int urgent, char *data, int len)
static void raw_sent(Plug plug, int bufsize)
{
Raw raw = (Raw) plug;
Raw raw = FROMFIELD(plug, struct raw_backend_data, plugvt);
raw->bufsize = bufsize;
}
static const Plug_vtable Raw_plugvt = {
raw_log,
raw_closing,
raw_receive,
raw_sent
};
/*
* Called to set up the raw connection.
*
@ -115,12 +121,6 @@ static const char *raw_init(void *frontend_handle, void **backend_handle,
const char *host, int port, char **realhost,
int nodelay, int keepalive)
{
static const struct plug_function_table fn_table = {
raw_log,
raw_closing,
raw_receive,
raw_sent
};
SockAddr addr;
const char *err;
Raw raw;
@ -128,7 +128,7 @@ static const char *raw_init(void *frontend_handle, void **backend_handle,
char *loghost;
raw = snew(struct raw_backend_data);
raw->fn = &fn_table;
raw->plugvt = &Raw_plugvt;
raw->s = NULL;
raw->closed_on_socket_error = FALSE;
*backend_handle = raw;
@ -157,7 +157,7 @@ static const char *raw_init(void *frontend_handle, void **backend_handle,
* Open socket.
*/
raw->s = new_connection(addr, *realhost, port, 0, 1, nodelay, keepalive,
(Plug) raw, conf);
&raw->plugvt, conf);
if ((err = sk_socket_error(raw->s)) != NULL)
return err;

Просмотреть файл

@ -12,9 +12,6 @@
#define RLOGIN_MAX_BACKLOG 4096
typedef struct rlogin_tag {
const struct plug_function_table *fn;
/* the above field _must_ be first in the structure */
Socket s;
int closed_on_socket_error;
int bufsize;
@ -27,6 +24,8 @@ typedef struct rlogin_tag {
/* In case we need to read a username from the terminal before starting */
prompts_t *prompt;
const Plug_vtable *plugvt;
} *Rlogin;
static void rlogin_size(void *handle, int width, int height);
@ -40,7 +39,7 @@ static void c_write(Rlogin rlogin, const void *buf, int len)
static void rlogin_log(Plug plug, int type, SockAddr addr, int port,
const char *error_msg, int error_code)
{
Rlogin rlogin = (Rlogin) plug;
Rlogin rlogin = FROMFIELD(plug, struct rlogin_tag, plugvt);
backend_socket_log(rlogin->frontend, type, addr, port,
error_msg, error_code,
rlogin->conf, !rlogin->firstbyte);
@ -49,7 +48,7 @@ static void rlogin_log(Plug plug, int type, SockAddr addr, int port,
static void rlogin_closing(Plug plug, const char *error_msg, int error_code,
int calling_back)
{
Rlogin rlogin = (Rlogin) plug;
Rlogin rlogin = FROMFIELD(plug, struct rlogin_tag, plugvt);
/*
* We don't implement independent EOF in each direction for Telnet
@ -73,7 +72,7 @@ static void rlogin_closing(Plug plug, const char *error_msg, int error_code,
static void rlogin_receive(Plug plug, int urgent, char *data, int len)
{
Rlogin rlogin = (Rlogin) plug;
Rlogin rlogin = FROMFIELD(plug, struct rlogin_tag, plugvt);
if (urgent == 2) {
char c;
@ -109,7 +108,7 @@ static void rlogin_receive(Plug plug, int urgent, char *data, int len)
static void rlogin_sent(Plug plug, int bufsize)
{
Rlogin rlogin = (Rlogin) plug;
Rlogin rlogin = FROMFIELD(plug, struct rlogin_tag, plugvt);
rlogin->bufsize = bufsize;
}
@ -134,6 +133,13 @@ static void rlogin_startup(Rlogin rlogin, const char *ruser)
rlogin->prompt = NULL;
}
static const Plug_vtable Rlogin_plugvt = {
rlogin_log,
rlogin_closing,
rlogin_receive,
rlogin_sent
};
/*
* Called to set up the rlogin connection.
*
@ -147,12 +153,6 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
const char *host, int port, char **realhost,
int nodelay, int keepalive)
{
static const struct plug_function_table fn_table = {
rlogin_log,
rlogin_closing,
rlogin_receive,
rlogin_sent
};
SockAddr addr;
const char *err;
Rlogin rlogin;
@ -161,7 +161,7 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
char *loghost;
rlogin = snew(struct rlogin_tag);
rlogin->fn = &fn_table;
rlogin->plugvt = &Rlogin_plugvt;
rlogin->s = NULL;
rlogin->closed_on_socket_error = FALSE;
rlogin->frontend = frontend_handle;
@ -191,7 +191,7 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
* Open socket.
*/
rlogin->s = new_connection(addr, *realhost, port, 1, 0,
nodelay, keepalive, (Plug) rlogin, conf);
nodelay, keepalive, &rlogin->plugvt, conf);
if ((err = sk_socket_error(rlogin->s)) != NULL)
return err;

40
ssh.c
Просмотреть файл

@ -878,15 +878,14 @@ enum RekeyClass {
};
struct ssh_tag {
const struct plug_function_table *fn;
/* the above field _must_ be first in the structure */
char *v_c, *v_s;
void *exhash;
BinarySink *exhash_bs;
Socket s;
const Plug_vtable *plugvt;
void *ldisc;
void *logctx;
@ -3593,7 +3592,7 @@ static int ssh_do_close(Ssh ssh, int notify_exit)
static void ssh_socket_log(Plug plug, int type, SockAddr addr, int port,
const char *error_msg, int error_code)
{
Ssh ssh = (Ssh) plug;
Ssh ssh = FROMFIELD(plug, struct ssh_tag, plugvt);
/*
* While we're attempting connection sharing, don't loudly log
@ -3646,7 +3645,7 @@ void ssh_connshare_log(Ssh ssh, int event, const char *logtext,
static void ssh_closing(Plug plug, const char *error_msg, int error_code,
int calling_back)
{
Ssh ssh = (Ssh) plug;
Ssh ssh = FROMFIELD(plug, struct ssh_tag, plugvt);
ssh->incoming_data_seen_eof = TRUE;
ssh->incoming_data_eof_message = dupstr(error_msg);
queue_idempotent_callback(&ssh->incoming_data_consumer);
@ -3654,7 +3653,7 @@ static void ssh_closing(Plug plug, const char *error_msg, int error_code,
static void ssh_receive(Plug plug, int urgent, char *data, int len)
{
Ssh ssh = (Ssh) plug;
Ssh ssh = FROMFIELD(plug, struct ssh_tag, plugvt);
/* Log raw data, if we're in that mode. */
if (ssh->logctx)
@ -3671,7 +3670,7 @@ static void ssh_receive(Plug plug, int urgent, char *data, int len)
static void ssh_sent(Plug plug, int bufsize)
{
Ssh ssh = (Ssh) plug;
Ssh ssh = FROMFIELD(plug, struct ssh_tag, plugvt);
/*
* If the send backlog on the SSH socket itself clears, we
* should unthrottle the whole world if it was throttled.
@ -3732,6 +3731,14 @@ static int ssh_test_for_upstream(const char *host, int port, Conf *conf)
return ret;
}
static const Plug_vtable Ssh_plugvt = {
ssh_socket_log,
ssh_closing,
ssh_receive,
ssh_sent,
NULL
};
/*
* Connect to specified host and port.
* Returns an error message, or NULL on success.
@ -3741,14 +3748,6 @@ static int ssh_test_for_upstream(const char *host, int port, Conf *conf)
static const char *connect_to_host(Ssh ssh, const char *host, int port,
char **realhost, int nodelay, int keepalive)
{
static const struct plug_function_table fn_table = {
ssh_socket_log,
ssh_closing,
ssh_receive,
ssh_sent,
NULL
};
SockAddr addr;
const char *err;
char *loghost;
@ -3757,7 +3756,7 @@ static const char *connect_to_host(Ssh ssh, const char *host, int port,
ssh_hostport_setup(host, port, ssh->conf,
&ssh->savedhost, &ssh->savedport, &loghost);
ssh->fn = &fn_table; /* make 'ssh' usable as a Plug */
ssh->plugvt = &Ssh_plugvt;
/*
* Try connection-sharing, in case that means we don't open a
@ -3770,8 +3769,9 @@ static const char *connect_to_host(Ssh ssh, const char *host, int port,
*/
ssh->connshare = NULL;
ssh->attempting_connshare = TRUE; /* affects socket logging behaviour */
ssh->s = ssh_connection_sharing_init(ssh->savedhost, ssh->savedport,
ssh->conf, ssh, &ssh->connshare);
ssh->s = ssh_connection_sharing_init(
ssh->savedhost, ssh->savedport, ssh->conf, ssh, &ssh->plugvt,
&ssh->connshare);
ssh->attempting_connshare = FALSE;
if (ssh->s != NULL) {
/*
@ -3801,7 +3801,7 @@ static const char *connect_to_host(Ssh ssh, const char *host, int port,
ssh->s = new_connection(addr, *realhost, port,
0, 1, nodelay, keepalive,
(Plug) ssh, ssh->conf);
&ssh->plugvt, ssh->conf);
if ((err = sk_socket_error(ssh->s)) != NULL) {
ssh->s = NULL;
notify_remote_exit(ssh->frontend);
@ -4090,7 +4090,7 @@ static void ssh_disconnect(Ssh ssh, const char *client_reason,
}
ssh->close_expected = TRUE;
ssh->clean_exit = clean_exit;
ssh_closing((Plug)ssh, error, 0, 0);
ssh_closing(&ssh->plugvt, error, 0, 0);
sfree(error);
}

5
ssh.h
Просмотреть файл

@ -22,8 +22,9 @@ void sshfwd_x11_sharing_handover(struct ssh_channel *c,
const void *initial_data, int initial_len);
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);
extern Socket ssh_connection_sharing_init(
const char *host, int port, Conf *conf, Ssh ssh, Plug sshplug,
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);

Просмотреть файл

@ -140,23 +140,19 @@
#include "ssh.h"
struct ssh_sharing_state {
const struct plug_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
char *sockname; /* the socket name, kept for cleanup */
Socket listensock; /* the master listening Socket */
tree234 *connections; /* holds ssh_sharing_connstates */
unsigned nextid; /* preferred id for next connstate */
Ssh ssh; /* instance of the ssh backend */
char *server_verstring; /* server version string after "SSH-" */
const Plug_vtable *plugvt;
};
struct share_globreq;
struct ssh_sharing_connstate {
const struct plug_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
unsigned id; /* used to identify this downstream in log messages */
Socket sock; /* the Socket for this connection */
@ -203,6 +199,8 @@ struct ssh_sharing_connstate {
/* Global requests we've sent on to the server, pending replies. */
struct share_globreq *globreq_head, *globreq_tail;
const Plug_vtable *plugvt;
};
struct share_halfchannel {
@ -902,7 +900,8 @@ static void share_disconnect(struct ssh_sharing_connstate *cs,
static void share_closing(Plug plug, const char *error_msg, int error_code,
int calling_back)
{
struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)plug;
struct ssh_sharing_connstate *cs = FROMFIELD(
plug, struct ssh_sharing_connstate, plugvt);
if (error_msg) {
#ifdef BROKEN_PIPE_ERROR_CODE
@ -1770,7 +1769,8 @@ static void share_got_pkt_from_downstream(struct ssh_sharing_connstate *cs,
static void share_receive(Plug plug, int urgent, char *data, int len)
{
struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)plug;
struct ssh_sharing_connstate *cs = FROMFIELD(
plug, struct ssh_sharing_connstate, plugvt);
static const char expected_verstring_prefix[] =
"SSHCONNECTION@putty.projects.tartarus.org-2.0-";
unsigned char c;
@ -1846,7 +1846,8 @@ static void share_receive(Plug plug, int urgent, char *data, int len)
static void share_sent(Plug plug, int bufsize)
{
/* struct ssh_sharing_connstate *cs = (struct ssh_sharing_connstate *)plug; */
/* struct ssh_sharing_connstate *cs = FROMFIELD(
plug, struct ssh_sharing_connstate, plugvt); */
/*
* We do nothing here, because we expect that there won't be a
@ -1861,7 +1862,8 @@ static void share_sent(Plug plug, int bufsize)
static void share_listen_closing(Plug plug, const char *error_msg,
int error_code, int calling_back)
{
struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)plug;
struct ssh_sharing_state *sharestate = FROMFIELD(
plug, struct ssh_sharing_state, plugvt);
if (error_msg)
ssh_sharing_logf(sharestate->ssh, 0,
"listening socket: %s", error_msg);
@ -1915,17 +1917,19 @@ void share_activate(void *state, const char *server_verstring)
}
}
static const Plug_vtable ssh_sharing_conn_plugvt = {
NULL, /* no log function, because that's for outgoing connections */
share_closing,
share_receive,
share_sent,
NULL /* no accepting function, because we've already done it */
};
static int share_listen_accepting(Plug plug,
accept_fn_t constructor, accept_ctx_t ctx)
{
static const struct plug_function_table connection_fn_table = {
NULL, /* no log function, because that's for outgoing connections */
share_closing,
share_receive,
share_sent,
NULL /* no accepting function, because we've already done it */
};
struct ssh_sharing_state *sharestate = (struct ssh_sharing_state *)plug;
struct ssh_sharing_state *sharestate = FROMFIELD(
plug, struct ssh_sharing_state, plugvt);
struct ssh_sharing_connstate *cs;
const char *err;
char *peerinfo;
@ -1934,7 +1938,7 @@ static int share_listen_accepting(Plug plug,
* A new downstream has connected to us.
*/
cs = snew(struct ssh_sharing_connstate);
cs->fn = &connection_fn_table;
cs->plugvt = &ssh_sharing_conn_plugvt;
cs->parent = sharestate;
if ((cs->id = share_find_unused_id(sharestate, sharestate->nextid)) == 0 &&
@ -1946,7 +1950,7 @@ static int share_listen_accepting(Plug plug,
if (sharestate->nextid == 0)
sharestate->nextid++; /* only happens in VERY long-running upstreams */
cs->sock = constructor(ctx, (Plug) cs);
cs->sock = constructor(ctx, &cs->plugvt);
if ((err = sk_socket_error(cs->sock)) != NULL) {
sfree(cs);
return err != NULL;
@ -2034,30 +2038,32 @@ static void nullplug_closing(Plug plug, const char *error_msg, int error_code,
static void nullplug_receive(Plug plug, int urgent, char *data, int len) {}
static void nullplug_sent(Plug plug, int bufsize) {}
static const Plug_vtable nullplug_plugvt = {
nullplug_socket_log,
nullplug_closing,
nullplug_receive,
nullplug_sent,
NULL
};
struct nullplug {
const Plug_vtable *plugvt;
};
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;
struct nullplug np;
np.fn = &fn_table;
np.plugvt = &nullplug_plugvt;
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,
result = platform_ssh_share(sockname, conf, &np.plugvt, (Plug)NULL, &sock,
&logtext, &ds_err, &us_err, FALSE, TRUE);
sfree(logtext);
@ -2075,6 +2081,14 @@ int ssh_share_test_for_upstream(const char *host, int port, Conf *conf)
}
}
static const Plug_vtable ssh_sharing_listen_plugvt = {
NULL, /* no log function, because that's for outgoing connections */
share_listen_closing,
NULL, /* no receive function on a listening socket */
NULL, /* no sent function on a listening socket */
share_listen_accepting
};
/*
* Init function for connection sharing. We either open a listening
* socket and become an upstream, or connect to an existing one and
@ -2086,16 +2100,9 @@ int ssh_share_test_for_upstream(const char *host, int port, Conf *conf)
* upstream) we return NULL.
*/
Socket ssh_connection_sharing_init(const char *host, int port,
Conf *conf, Ssh ssh, void **state)
Conf *conf, Ssh ssh, Plug sshplug,
void **state)
{
static const struct plug_function_table listen_fn_table = {
NULL, /* no log function, because that's for outgoing connections */
share_listen_closing,
NULL, /* no receive function on a listening socket */
NULL, /* no sent function on a listening socket */
share_listen_accepting
};
int result, can_upstream, can_downstream;
char *logtext, *ds_err, *us_err;
char *sockname;
@ -2118,7 +2125,7 @@ Socket ssh_connection_sharing_init(const char *host, int port,
* to be an upstream.
*/
sharestate = snew(struct ssh_sharing_state);
sharestate->fn = &listen_fn_table;
sharestate->plugvt = &ssh_sharing_listen_plugvt;
sharestate->listensock = NULL;
/*
@ -2130,9 +2137,9 @@ Socket ssh_connection_sharing_init(const char *host, int port,
*/
sock = NULL;
logtext = ds_err = us_err = NULL;
result = platform_ssh_share(sockname, conf, (Plug)ssh,
(Plug)sharestate, &sock, &logtext, &ds_err,
&us_err, can_upstream, can_downstream);
result = platform_ssh_share(
sockname, conf, sshplug, &sharestate->plugvt, &sock, &logtext,
&ds_err, &us_err, can_upstream, can_downstream);
ssh_connshare_log(ssh, result, logtext, ds_err, us_err);
sfree(logtext);
sfree(ds_err);

Просмотреть файл

@ -171,9 +171,6 @@ static const struct Opt *const opts[] = {
};
typedef struct telnet_tag {
const struct plug_function_table *fn;
/* the above field _must_ be first in the structure */
Socket s;
int closed_on_socket_error;
@ -200,6 +197,8 @@ typedef struct telnet_tag {
Conf *conf;
Pinger pinger;
const Plug_vtable *plugvt;
} *Telnet;
#define TELNET_MAX_BACKLOG 4096
@ -645,7 +644,7 @@ static void do_telnet_read(Telnet telnet, char *buf, int len)
static void telnet_log(Plug plug, int type, SockAddr addr, int port,
const char *error_msg, int error_code)
{
Telnet telnet = (Telnet) plug;
Telnet telnet = FROMFIELD(plug, struct telnet_tag, plugvt);
backend_socket_log(telnet->frontend, type, addr, port,
error_msg, error_code, telnet->conf,
telnet->session_started);
@ -654,7 +653,7 @@ static void telnet_log(Plug plug, int type, SockAddr addr, int port,
static void telnet_closing(Plug plug, const char *error_msg, int error_code,
int calling_back)
{
Telnet telnet = (Telnet) plug;
Telnet telnet = FROMFIELD(plug, struct telnet_tag, plugvt);
/*
* We don't implement independent EOF in each direction for Telnet
@ -678,7 +677,7 @@ static void telnet_closing(Plug plug, const char *error_msg, int error_code,
static void telnet_receive(Plug plug, int urgent, char *data, int len)
{
Telnet telnet = (Telnet) plug;
Telnet telnet = FROMFIELD(plug, struct telnet_tag, plugvt);
if (urgent)
telnet->in_synch = TRUE;
telnet->session_started = TRUE;
@ -687,10 +686,17 @@ static void telnet_receive(Plug plug, int urgent, char *data, int len)
static void telnet_sent(Plug plug, int bufsize)
{
Telnet telnet = (Telnet) plug;
Telnet telnet = FROMFIELD(plug, struct telnet_tag, plugvt);
telnet->bufsize = bufsize;
}
static const Plug_vtable Telnet_plugvt = {
telnet_log,
telnet_closing,
telnet_receive,
telnet_sent
};
/*
* Called to set up the Telnet connection.
*
@ -703,12 +709,6 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
Conf *conf, const char *host, int port,
char **realhost, int nodelay, int keepalive)
{
static const struct plug_function_table fn_table = {
telnet_log,
telnet_closing,
telnet_receive,
telnet_sent
};
SockAddr addr;
const char *err;
Telnet telnet;
@ -716,7 +716,7 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
int addressfamily;
telnet = snew(struct telnet_tag);
telnet->fn = &fn_table;
telnet->plugvt = &Telnet_plugvt;
telnet->conf = conf_copy(conf);
telnet->s = NULL;
telnet->closed_on_socket_error = FALSE;
@ -751,8 +751,8 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
/*
* Open socket.
*/
telnet->s = new_connection(addr, *realhost, port, 0, 1,
nodelay, keepalive, (Plug) telnet, telnet->conf);
telnet->s = new_connection(addr, *realhost, port, 0, 1, nodelay, keepalive,
&telnet->plugvt, telnet->conf);
if ((err = sk_socket_error(telnet->s)) != NULL)
return err;

Просмотреть файл

@ -312,7 +312,7 @@ int init_ucs(struct unicode_data *ucsdata, char *line_codepage,
/*
* Spare function exported directly from uxnet.c.
*/
void *sk_getxdmdata(void *sock, int *lenp);
void *sk_getxdmdata(Socket sock, int *lenp);
/*
* General helpful Unix stuff: more helpful version of the FD_SET

Просмотреть файл

@ -46,16 +46,6 @@ union sockaddr_union {
struct sockaddr_un su;
};
/*
* We used to typedef struct Socket_tag *Socket.
*
* Since we have made the networking abstraction slightly more
* abstract, Socket no longer means a tcp socket (it could mean
* an ssl socket). So now we must use Actual_Socket when we know
* we are talking about a tcp socket.
*/
typedef struct Socket_tag *Actual_Socket;
/*
* Mutable state that goes with a SockAddr: stores information
* about where in the list of candidate IP(v*) addresses we've
@ -69,9 +59,8 @@ struct SockAddrStep_tag {
int curraddr;
};
struct Socket_tag {
struct socket_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
typedef struct NetSocket NetSocket;
struct NetSocket {
const char *error;
int s;
Plug plug;
@ -98,7 +87,9 @@ struct Socket_tag {
* example. So here we define `parent' and `child' pointers to
* track this link.
*/
Actual_Socket parent, child;
NetSocket *parent, *child;
const Socket_vtable *sockvt;
};
struct SockAddr_tag {
@ -148,11 +139,11 @@ struct SockAddr_tag {
static tree234 *sktree;
static void uxsel_tell(Actual_Socket s);
static void uxsel_tell(NetSocket *s);
static int cmpfortree(void *av, void *bv)
{
Actual_Socket a = (Actual_Socket) av, b = (Actual_Socket) bv;
NetSocket *a = (NetSocket *) av, *b = (NetSocket *) bv;
int as = a->s, bs = b->s;
if (as < bs)
return -1;
@ -167,7 +158,7 @@ static int cmpfortree(void *av, void *bv)
static int cmpforsearch(void *av, void *bv)
{
Actual_Socket b = (Actual_Socket) bv;
NetSocket *b = (NetSocket *) bv;
int as = *(int *)av, bs = b->s;
if (as < bs)
return -1;
@ -183,7 +174,7 @@ void sk_init(void)
void sk_cleanup(void)
{
Actual_Socket s;
NetSocket *s;
int i;
if (sktree) {
@ -491,16 +482,16 @@ SockAddr sk_addr_dup(SockAddr addr)
return addr;
}
static Plug sk_tcp_plug(Socket sock, Plug p)
static Plug sk_net_plug(Socket sock, Plug p)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
Plug ret = s->plug;
if (p)
s->plug = p;
return ret;
}
static void sk_tcp_flush(Socket s)
static void sk_net_flush(Socket s)
{
/*
* We send data to the socket as soon as we can anyway,
@ -508,36 +499,36 @@ static void sk_tcp_flush(Socket s)
*/
}
static void sk_tcp_close(Socket s);
static int sk_tcp_write(Socket s, const void *data, int len);
static int sk_tcp_write_oob(Socket s, const void *data, int len);
static void sk_tcp_write_eof(Socket s);
static void sk_tcp_set_frozen(Socket s, int is_frozen);
static char *sk_tcp_peer_info(Socket s);
static const char *sk_tcp_socket_error(Socket s);
static void sk_net_close(Socket s);
static int sk_net_write(Socket s, const void *data, int len);
static int sk_net_write_oob(Socket s, const void *data, int len);
static void sk_net_write_eof(Socket s);
static void sk_net_set_frozen(Socket s, int is_frozen);
static char *sk_net_peer_info(Socket s);
static const char *sk_net_socket_error(Socket s);
static struct socket_function_table tcp_fn_table = {
sk_tcp_plug,
sk_tcp_close,
sk_tcp_write,
sk_tcp_write_oob,
sk_tcp_write_eof,
sk_tcp_flush,
sk_tcp_set_frozen,
sk_tcp_socket_error,
sk_tcp_peer_info,
static struct Socket_vtable NetSocket_sockvt = {
sk_net_plug,
sk_net_close,
sk_net_write,
sk_net_write_oob,
sk_net_write_eof,
sk_net_flush,
sk_net_set_frozen,
sk_net_socket_error,
sk_net_peer_info,
};
static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug)
static Socket sk_net_accept(accept_ctx_t ctx, Plug plug)
{
int sockfd = ctx.i;
Actual_Socket ret;
NetSocket *ret;
/*
* Create Socket structure.
* Create NetSocket structure.
*/
ret = snew(struct Socket_tag);
ret->fn = &tcp_fn_table;
ret = snew(NetSocket);
ret->sockvt = &NetSocket_sockvt;
ret->error = NULL;
ret->plug = plug;
bufchain_init(&ret->output_data);
@ -558,7 +549,7 @@ static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug)
if (ret->s < 0) {
ret->error = strerror(errno);
return (Socket) ret;
return &ret->sockvt;
}
ret->oobinline = 0;
@ -566,10 +557,10 @@ static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug)
uxsel_tell(ret);
add234(sktree, ret);
return (Socket) ret;
return &ret->sockvt;
}
static int try_connect(Actual_Socket sock)
static int try_connect(NetSocket *sock)
{
int s;
union sockaddr_union u;
@ -771,14 +762,14 @@ static int try_connect(Actual_Socket sock)
Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
int nodelay, int keepalive, Plug plug)
{
Actual_Socket ret;
NetSocket *ret;
int err;
/*
* Create Socket structure.
* Create NetSocket structure.
*/
ret = snew(struct Socket_tag);
ret->fn = &tcp_fn_table;
ret = snew(NetSocket);
ret->sockvt = &NetSocket_sockvt;
ret->error = NULL;
ret->plug = plug;
bufchain_init(&ret->output_data);
@ -810,7 +801,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
if (err)
ret->error = strerror(err);
return (Socket) ret;
return &ret->sockvt;
}
Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
@ -824,16 +815,16 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
union sockaddr_union u;
union sockaddr_union *addr;
int addrlen;
Actual_Socket ret;
NetSocket *ret;
int retcode;
int address_family;
int on = 1;
/*
* Create Socket structure.
* Create NetSocket structure.
*/
ret = snew(struct Socket_tag);
ret->fn = &tcp_fn_table;
ret = snew(NetSocket);
ret->sockvt = &NetSocket_sockvt;
ret->error = NULL;
ret->plug = plug;
bufchain_init(&ret->output_data);
@ -884,7 +875,7 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
if (s < 0) {
ret->error = strerror(errno);
return (Socket) ret;
return &ret->sockvt;
}
cloexec(s);
@ -895,7 +886,7 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
(const char *)&on, sizeof(on)) < 0) {
ret->error = strerror(errno);
close(s);
return (Socket) ret;
return &ret->sockvt;
}
retcode = -1;
@ -973,13 +964,13 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
if (retcode < 0) {
close(s);
ret->error = strerror(errno);
return (Socket) ret;
return &ret->sockvt;
}
if (listen(s, SOMAXCONN) < 0) {
close(s);
ret->error = strerror(errno);
return (Socket) ret;
return &ret->sockvt;
}
#ifndef NO_IPV6
@ -988,10 +979,12 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
* IPv4 listening socket and link it to this one.
*/
if (address_family == AF_INET6 && orig_address_family == ADDRTYPE_UNSPEC) {
Actual_Socket other;
NetSocket *other;
other = (Actual_Socket) sk_newlistener(srcaddr, port, plug,
local_host_only, ADDRTYPE_IPV4);
other = FROMFIELD(
sk_newlistener(srcaddr, port, plug,
local_host_only, ADDRTYPE_IPV4),
NetSocket, sockvt);
if (other) {
if (!other->error) {
@ -1002,7 +995,7 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
* as IPv6, we must return an error overall. */
close(s);
sfree(ret);
return (Socket) other;
return &other->sockvt;
}
}
}
@ -1013,15 +1006,15 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
uxsel_tell(ret);
add234(sktree, ret);
return (Socket) ret;
return &ret->sockvt;
}
static void sk_tcp_close(Socket sock)
static void sk_net_close(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
if (s->child)
sk_tcp_close((Socket)s->child);
sk_net_close(&s->child->sockvt);
del234(sktree, s);
if (s->s >= 0) {
@ -1033,19 +1026,21 @@ static void sk_tcp_close(Socket sock)
sfree(s);
}
void *sk_getxdmdata(void *sock, int *lenp)
void *sk_getxdmdata(Socket sock, int *lenp)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s;
union sockaddr_union u;
socklen_t addrlen;
char *buf;
static unsigned int unix_addr = 0xFFFFFFFF;
/*
* We must check that this socket really _is_ an Actual_Socket.
* We must check that this socket really _is_ a NetSocket before
* downcasting it.
*/
if (s->fn != &tcp_fn_table)
if (*sock != &NetSocket_sockvt)
return NULL; /* failure */
s = FROMFIELD(sock, NetSocket, sockvt);
addrlen = sizeof(u);
if (getsockname(s->s, &u.sa, &addrlen) < 0)
@ -1090,7 +1085,7 @@ void *sk_getxdmdata(void *sock, int *lenp)
*/
static void socket_error_callback(void *vs)
{
Actual_Socket s = (Actual_Socket)vs;
NetSocket *s = (NetSocket *)vs;
/*
* Just in case other socket work has caused this socket to vanish
@ -1109,7 +1104,7 @@ static void socket_error_callback(void *vs)
* The function which tries to send on a socket once it's deemed
* writable.
*/
void try_send(Actual_Socket s)
void try_send(NetSocket *s)
{
while (s->sending_oob || bufchain_size(&s->output_data) > 0) {
int nsent;
@ -1189,9 +1184,9 @@ void try_send(Actual_Socket s)
uxsel_tell(s);
}
static int sk_tcp_write(Socket sock, const void *buf, int len)
static int sk_net_write(Socket sock, const void *buf, int len)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
assert(s->outgoingeof == EOF_NO);
@ -1215,9 +1210,9 @@ static int sk_tcp_write(Socket sock, const void *buf, int len)
return bufchain_size(&s->output_data);
}
static int sk_tcp_write_oob(Socket sock, const void *buf, int len)
static int sk_net_write_oob(Socket sock, const void *buf, int len)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
assert(s->outgoingeof == EOF_NO);
@ -1244,9 +1239,9 @@ static int sk_tcp_write_oob(Socket sock, const void *buf, int len)
return s->sending_oob;
}
static void sk_tcp_write_eof(Socket sock)
static void sk_net_write_eof(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
assert(s->outgoingeof == EOF_NO);
@ -1272,7 +1267,7 @@ static void net_select_result(int fd, int event)
{
int ret;
char buf[20480]; /* nice big buffer for plenty of speed */
Actual_Socket s;
NetSocket *s;
u_long atmark;
/* Find the Socket structure */
@ -1343,7 +1338,7 @@ static void net_select_result(int fd, int event)
if ((!s->addr || s->addr->superfamily != UNIX) &&
s->localhost_only && !sockaddr_is_loopback(&su.sa)) {
close(t); /* someone let nonlocal through?! */
} else if (plug_accepting(s->plug, sk_tcp_accept, actx)) {
} else if (plug_accepting(s->plug, sk_net_accept, actx)) {
close(t); /* denied or error */
}
break;
@ -1471,24 +1466,24 @@ const char *sk_addr_error(SockAddr addr)
{
return addr->error;
}
static const char *sk_tcp_socket_error(Socket sock)
static const char *sk_net_socket_error(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
return s->error;
}
static void sk_tcp_set_frozen(Socket sock, int is_frozen)
static void sk_net_set_frozen(Socket sock, int is_frozen)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
if (s->frozen == is_frozen)
return;
s->frozen = is_frozen;
uxsel_tell(s);
}
static char *sk_tcp_peer_info(Socket sock)
static char *sk_net_peer_info(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
union sockaddr_union addr;
socklen_t addrlen = sizeof(addr);
#ifndef NO_IPV6
@ -1532,7 +1527,7 @@ static char *sk_tcp_peer_info(Socket sock)
}
}
static void uxsel_tell(Actual_Socket s)
static void uxsel_tell(NetSocket *s)
{
int rwx = 0;
if (!s->pending_error) {
@ -1642,14 +1637,14 @@ Socket new_unix_listener(SockAddr listenaddr, Plug plug)
union sockaddr_union u;
union sockaddr_union *addr;
int addrlen;
Actual_Socket ret;
NetSocket *ret;
int retcode;
/*
* Create Socket structure.
* Create NetSocket structure.
*/
ret = snew(struct Socket_tag);
ret->fn = &tcp_fn_table;
ret = snew(NetSocket);
ret->sockvt = &NetSocket_sockvt;
ret->error = NULL;
ret->plug = plug;
bufchain_init(&ret->output_data);
@ -1674,7 +1669,7 @@ Socket new_unix_listener(SockAddr listenaddr, Plug plug)
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s < 0) {
ret->error = strerror(errno);
return (Socket) ret;
return &ret->sockvt;
}
cloexec(s);
@ -1690,20 +1685,20 @@ Socket new_unix_listener(SockAddr listenaddr, Plug plug)
if (unlink(u.su.sun_path) < 0 && errno != ENOENT) {
close(s);
ret->error = strerror(errno);
return (Socket) ret;
return &ret->sockvt;
}
retcode = bind(s, &addr->sa, addrlen);
if (retcode < 0) {
close(s);
ret->error = strerror(errno);
return (Socket) ret;
return &ret->sockvt;
}
if (listen(s, SOMAXCONN) < 0) {
close(s);
ret->error = strerror(errno);
return (Socket) ret;
return &ret->sockvt;
}
ret->s = s;
@ -1711,5 +1706,5 @@ Socket new_unix_listener(SockAddr listenaddr, Plug plug)
uxsel_tell(ret);
add234(sktree, ret);
return (Socket) ret;
return &ret->sockvt;
}

Просмотреть файл

@ -185,7 +185,7 @@ static void x11_closing(Plug plug, const char *error_msg, int error_code,
time_to_die = TRUE;
}
struct X11Connection {
const struct plug_function_table *fn;
const Plug_vtable *plugvt;
};
char *socketname;
@ -735,11 +735,20 @@ void run_client(void)
exit(1);
}
static const Plug_vtable X11Connection_plugvt = {
x11_log,
x11_closing,
x11_receive,
x11_sent,
NULL
};
void run_agent(void)
{
const char *err;
char *username, *socketdir;
struct pageant_listen_state *pl;
Plug pl_plug;
Socket sock;
unsigned long now;
int *fdlist;
@ -778,8 +787,8 @@ void run_agent(void)
exit(1);
}
socketname = dupprintf("%s/pageant.%d", socketdir, (int)getpid());
pl = pageant_listener_new();
sock = new_unix_listener(unix_sock_addr(socketname), (Plug)pl);
pl = pageant_listener_new(&pl_plug);
sock = new_unix_listener(unix_sock_addr(socketname), pl_plug);
if ((err = sk_socket_error(sock)) != NULL) {
fprintf(stderr, "pageant: %s: %s\n", socketname, err);
exit(1);
@ -800,14 +809,6 @@ void run_agent(void)
Socket s;
struct X11Connection *conn;
static const struct plug_function_table fn_table = {
x11_log,
x11_closing,
x11_receive,
x11_sent,
NULL
};
if (!display) {
fprintf(stderr, "pageant: no DISPLAY for -X mode\n");
exit(1);
@ -815,10 +816,10 @@ void run_agent(void)
disp = x11_setup_display(display, conf);
conn = snew(struct X11Connection);
conn->fn = &fn_table;
conn->plugvt = &X11Connection_plugvt;
s = new_connection(sk_addr_dup(disp->addr),
disp->realhost, disp->port,
0, 1, 0, 0, (Plug)conn, conf);
0, 1, 0, 0, &conn->plugvt, conf);
if ((err = sk_socket_error(s)) != NULL) {
fprintf(stderr, "pageant: unable to connect to X server: %s", err);
exit(1);

Просмотреть файл

@ -15,12 +15,7 @@
#include "network.h"
#include "proxy.h"
typedef struct Socket_localproxy_tag * Local_Proxy_Socket;
struct Socket_localproxy_tag {
const struct socket_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
typedef struct LocalProxySocket {
int to_cmd, from_cmd, cmd_err; /* fds */
char *error;
@ -31,7 +26,9 @@ struct Socket_localproxy_tag {
bufchain pending_input_data;
bufchain pending_error_data;
enum { EOF_NO, EOF_PENDING, EOF_SENT } outgoingeof;
};
const Socket_vtable *sockvt;
} LocalProxySocket;
static void localproxy_select_result(int fd, int event);
@ -43,8 +40,8 @@ static tree234 *localproxy_by_tofd;
static tree234 *localproxy_by_errfd;
static int localproxy_fromfd_cmp(void *av, void *bv)
{
Local_Proxy_Socket a = (Local_Proxy_Socket)av;
Local_Proxy_Socket b = (Local_Proxy_Socket)bv;
LocalProxySocket *a = (LocalProxySocket *)av;
LocalProxySocket *b = (LocalProxySocket *)bv;
if (a->from_cmd < b->from_cmd)
return -1;
if (a->from_cmd > b->from_cmd)
@ -54,7 +51,7 @@ static int localproxy_fromfd_cmp(void *av, void *bv)
static int localproxy_fromfd_find(void *av, void *bv)
{
int a = *(int *)av;
Local_Proxy_Socket b = (Local_Proxy_Socket)bv;
LocalProxySocket *b = (LocalProxySocket *)bv;
if (a < b->from_cmd)
return -1;
if (a > b->from_cmd)
@ -63,8 +60,8 @@ static int localproxy_fromfd_find(void *av, void *bv)
}
static int localproxy_tofd_cmp(void *av, void *bv)
{
Local_Proxy_Socket a = (Local_Proxy_Socket)av;
Local_Proxy_Socket b = (Local_Proxy_Socket)bv;
LocalProxySocket *a = (LocalProxySocket *)av;
LocalProxySocket *b = (LocalProxySocket *)bv;
if (a->to_cmd < b->to_cmd)
return -1;
if (a->to_cmd > b->to_cmd)
@ -74,7 +71,7 @@ static int localproxy_tofd_cmp(void *av, void *bv)
static int localproxy_tofd_find(void *av, void *bv)
{
int a = *(int *)av;
Local_Proxy_Socket b = (Local_Proxy_Socket)bv;
LocalProxySocket *b = (LocalProxySocket *)bv;
if (a < b->to_cmd)
return -1;
if (a > b->to_cmd)
@ -83,8 +80,8 @@ static int localproxy_tofd_find(void *av, void *bv)
}
static int localproxy_errfd_cmp(void *av, void *bv)
{
Local_Proxy_Socket a = (Local_Proxy_Socket)av;
Local_Proxy_Socket b = (Local_Proxy_Socket)bv;
LocalProxySocket *a = (LocalProxySocket *)av;
LocalProxySocket *b = (LocalProxySocket *)bv;
if (a->cmd_err < b->cmd_err)
return -1;
if (a->cmd_err > b->cmd_err)
@ -94,7 +91,7 @@ static int localproxy_errfd_cmp(void *av, void *bv)
static int localproxy_errfd_find(void *av, void *bv)
{
int a = *(int *)av;
Local_Proxy_Socket b = (Local_Proxy_Socket)bv;
LocalProxySocket *b = (LocalProxySocket *)bv;
if (a < b->cmd_err)
return -1;
if (a > b->cmd_err)
@ -106,7 +103,7 @@ static int localproxy_errfd_find(void *av, void *bv)
static Plug sk_localproxy_plug (Socket s, Plug p)
{
Local_Proxy_Socket ps = (Local_Proxy_Socket) s;
LocalProxySocket *ps = FROMFIELD(s, LocalProxySocket, sockvt);
Plug ret = ps->plug;
if (p)
ps->plug = p;
@ -115,7 +112,7 @@ static Plug sk_localproxy_plug (Socket s, Plug p)
static void sk_localproxy_close (Socket s)
{
Local_Proxy_Socket ps = (Local_Proxy_Socket) s;
LocalProxySocket *ps = FROMFIELD(s, LocalProxySocket, sockvt);
if (ps->to_cmd >= 0) {
del234(localproxy_by_tofd, ps);
@ -138,7 +135,7 @@ static void sk_localproxy_close (Socket s)
sfree(ps);
}
static int localproxy_try_send(Local_Proxy_Socket ps)
static int localproxy_try_send(LocalProxySocket *ps)
{
int sent = 0;
@ -177,7 +174,7 @@ static int localproxy_try_send(Local_Proxy_Socket ps)
static int sk_localproxy_write (Socket s, const void *data, int len)
{
Local_Proxy_Socket ps = (Local_Proxy_Socket) s;
LocalProxySocket *ps = FROMFIELD(s, LocalProxySocket, sockvt);
assert(ps->outgoingeof == EOF_NO);
@ -199,7 +196,7 @@ static int sk_localproxy_write_oob (Socket s, const void *data, int len)
static void sk_localproxy_write_eof (Socket s)
{
Local_Proxy_Socket ps = (Local_Proxy_Socket) s;
LocalProxySocket *ps = FROMFIELD(s, LocalProxySocket, sockvt);
assert(ps->outgoingeof == EOF_NO);
ps->outgoingeof = EOF_PENDING;
@ -209,13 +206,13 @@ static void sk_localproxy_write_eof (Socket s)
static void sk_localproxy_flush (Socket s)
{
/* Local_Proxy_Socket ps = (Local_Proxy_Socket) s; */
/* LocalProxySocket *ps = FROMFIELD(s, LocalProxySocket, sockvt); */
/* do nothing */
}
static void sk_localproxy_set_frozen (Socket s, int is_frozen)
{
Local_Proxy_Socket ps = (Local_Proxy_Socket) s;
LocalProxySocket *ps = FROMFIELD(s, LocalProxySocket, sockvt);
if (is_frozen)
uxsel_del(ps->from_cmd);
@ -225,13 +222,13 @@ static void sk_localproxy_set_frozen (Socket s, int is_frozen)
static const char * sk_localproxy_socket_error (Socket s)
{
Local_Proxy_Socket ps = (Local_Proxy_Socket) s;
LocalProxySocket *ps = FROMFIELD(s, LocalProxySocket, sockvt);
return ps->error;
}
static void localproxy_select_result(int fd, int event)
{
Local_Proxy_Socket s;
LocalProxySocket *s;
char buf[20480];
int ret;
@ -263,6 +260,18 @@ static void localproxy_select_result(int fd, int event)
}
}
static const Socket_vtable LocalProxySocket_sockvt = {
sk_localproxy_plug,
sk_localproxy_close,
sk_localproxy_write,
sk_localproxy_write_oob,
sk_localproxy_write_eof,
sk_localproxy_flush,
sk_localproxy_set_frozen,
sk_localproxy_socket_error,
NULL, /* peer_info */
};
Socket platform_new_connection(SockAddr addr, const char *hostname,
int port, int privport,
int oobinline, int nodelay, int keepalive,
@ -270,27 +279,15 @@ Socket platform_new_connection(SockAddr addr, const char *hostname,
{
char *cmd;
static const struct socket_function_table socket_fn_table = {
sk_localproxy_plug,
sk_localproxy_close,
sk_localproxy_write,
sk_localproxy_write_oob,
sk_localproxy_write_eof,
sk_localproxy_flush,
sk_localproxy_set_frozen,
sk_localproxy_socket_error,
NULL, /* peer_info */
};
Local_Proxy_Socket ret;
LocalProxySocket *ret;
int to_cmd_pipe[2], from_cmd_pipe[2], cmd_err_pipe[2], pid, proxytype;
proxytype = conf_get_int(conf, CONF_proxy_type);
if (proxytype != PROXY_CMD && proxytype != PROXY_FUZZ)
return NULL;
ret = snew(struct Socket_localproxy_tag);
ret->fn = &socket_fn_table;
ret = snew(LocalProxySocket);
ret->sockvt = &LocalProxySocket_sockvt;
ret->plug = plug;
ret->error = NULL;
ret->outgoingeof = EOF_NO;
@ -329,7 +326,7 @@ Socket platform_new_connection(SockAddr addr, const char *hostname,
(cmd_err_pipe[0] == 0 && pipe(cmd_err_pipe) < 0)) {
ret->error = dupprintf("pipe: %s", strerror(errno));
sfree(cmd);
return (Socket)ret;
return &ret->sockvt;
}
cloexec(to_cmd_pipe[1]);
cloexec(from_cmd_pipe[0]);
@ -341,7 +338,7 @@ Socket platform_new_connection(SockAddr addr, const char *hostname,
if (pid < 0) {
ret->error = dupprintf("fork: %s", strerror(errno));
sfree(cmd);
return (Socket)ret;
return &ret->sockvt;
} else if (pid == 0) {
close(0);
close(1);
@ -375,13 +372,13 @@ Socket platform_new_connection(SockAddr addr, const char *hostname,
if (ret->to_cmd == -1) {
ret->error = dupprintf("/dev/null: %s", strerror(errno));
sfree(cmd);
return (Socket)ret;
return &ret->sockvt;
}
ret->from_cmd = open(cmd, O_RDONLY);
if (ret->from_cmd == -1) {
ret->error = dupprintf("%s: %s", cmd, strerror(errno));
sfree(cmd);
return (Socket)ret;
return &ret->sockvt;
}
sfree(cmd);
ret->cmd_err = -1;
@ -406,5 +403,5 @@ Socket platform_new_connection(SockAddr addr, const char *hostname,
/* We are responsible for this and don't need it any more */
sk_addr_free(addr);
return (Socket) ret;
return &ret->sockvt;
}

Просмотреть файл

@ -12,12 +12,7 @@
#include "putty.h"
#include "network.h"
typedef struct Socket_handle_tag *Handle_Socket;
struct Socket_handle_tag {
const struct socket_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
typedef struct HandleSocket {
HANDLE send_H, recv_H, stderr_H;
struct handle *send_h, *recv_h, *stderr_h;
@ -47,29 +42,31 @@ struct Socket_handle_tag {
char *error;
Plug plug;
};
const Socket_vtable *sockvt;
} HandleSocket;
static int handle_gotdata(struct handle *h, void *data, int len)
{
Handle_Socket ps = (Handle_Socket) handle_get_privdata(h);
HandleSocket *hs = (HandleSocket *)handle_get_privdata(h);
if (len < 0) {
plug_closing(ps->plug, "Read error from handle", 0, 0);
plug_closing(hs->plug, "Read error from handle", 0, 0);
return 0;
} else if (len == 0) {
plug_closing(ps->plug, NULL, 0, 0);
plug_closing(hs->plug, NULL, 0, 0);
return 0;
} else {
assert(ps->frozen != FROZEN && ps->frozen != THAWING);
if (ps->frozen == FREEZING) {
assert(hs->frozen != FROZEN && hs->frozen != THAWING);
if (hs->frozen == FREEZING) {
/*
* If we've received data while this socket is supposed to
* be frozen (because the read winhandl.c started before
* sk_set_frozen was called has now returned) then buffer
* the data for when we unfreeze.
*/
bufchain_add(&ps->inputdata, data, len);
ps->frozen = FROZEN;
bufchain_add(&hs->inputdata, data, len);
hs->frozen = FROZEN;
/*
* And return a very large backlog, to prevent further
@ -77,7 +74,7 @@ static int handle_gotdata(struct handle *h, void *data, int len)
*/
return INT_MAX;
} else {
plug_receive(ps->plug, 0, data, len);
plug_receive(hs->plug, 0, data, len);
return 0;
}
}
@ -85,63 +82,63 @@ static int handle_gotdata(struct handle *h, void *data, int len)
static int handle_stderr(struct handle *h, void *data, int len)
{
Handle_Socket ps = (Handle_Socket) handle_get_privdata(h);
HandleSocket *hs = (HandleSocket *)handle_get_privdata(h);
if (len > 0)
log_proxy_stderr(ps->plug, &ps->stderrdata, data, len);
log_proxy_stderr(hs->plug, &hs->stderrdata, data, len);
return 0;
}
static void handle_sentdata(struct handle *h, int new_backlog)
{
Handle_Socket ps = (Handle_Socket) handle_get_privdata(h);
HandleSocket *hs = (HandleSocket *)handle_get_privdata(h);
if (new_backlog < 0) {
/* Special case: this is actually reporting an error writing
* to the underlying handle, and our input value is the error
* code itself, negated. */
plug_closing(ps->plug, win_strerror(-new_backlog), -new_backlog, 0);
plug_closing(hs->plug, win_strerror(-new_backlog), -new_backlog, 0);
return;
}
plug_sent(ps->plug, new_backlog);
plug_sent(hs->plug, new_backlog);
}
static Plug sk_handle_plug(Socket s, Plug p)
{
Handle_Socket ps = (Handle_Socket) s;
Plug ret = ps->plug;
HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt);
Plug ret = hs->plug;
if (p)
ps->plug = p;
hs->plug = p;
return ret;
}
static void sk_handle_close(Socket s)
{
Handle_Socket ps = (Handle_Socket) s;
HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt);
if (ps->defer_close) {
ps->deferred_close = TRUE;
if (hs->defer_close) {
hs->deferred_close = TRUE;
return;
}
handle_free(ps->send_h);
handle_free(ps->recv_h);
CloseHandle(ps->send_H);
if (ps->recv_H != ps->send_H)
CloseHandle(ps->recv_H);
bufchain_clear(&ps->inputdata);
bufchain_clear(&ps->stderrdata);
handle_free(hs->send_h);
handle_free(hs->recv_h);
CloseHandle(hs->send_H);
if (hs->recv_H != hs->send_H)
CloseHandle(hs->recv_H);
bufchain_clear(&hs->inputdata);
bufchain_clear(&hs->stderrdata);
sfree(ps);
sfree(hs);
}
static int sk_handle_write(Socket s, const void *data, int len)
{
Handle_Socket ps = (Handle_Socket) s;
HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt);
return handle_write(ps->send_h, data, len);
return handle_write(hs->send_h, data, len);
}
static int sk_handle_write_oob(Socket s, const void *data, int len)
@ -155,20 +152,20 @@ static int sk_handle_write_oob(Socket s, const void *data, int len)
static void sk_handle_write_eof(Socket s)
{
Handle_Socket ps = (Handle_Socket) s;
HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt);
handle_write_eof(ps->send_h);
handle_write_eof(hs->send_h);
}
static void sk_handle_flush(Socket s)
{
/* Handle_Socket ps = (Handle_Socket) s; */
/* HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt); */
/* do nothing */
}
static void handle_socket_unfreeze(void *psv)
static void handle_socket_unfreeze(void *hsv)
{
Handle_Socket ps = (Handle_Socket) psv;
HandleSocket *hs = (HandleSocket *)hsv;
void *data;
int len;
@ -176,49 +173,49 @@ static void handle_socket_unfreeze(void *psv)
* If we've been put into a state other than THAWING since the
* last callback, then we're done.
*/
if (ps->frozen != THAWING)
if (hs->frozen != THAWING)
return;
/*
* Get some of the data we've buffered.
*/
bufchain_prefix(&ps->inputdata, &data, &len);
bufchain_prefix(&hs->inputdata, &data, &len);
assert(len > 0);
/*
* Hand it off to the plug. Be careful of re-entrance - that might
* have the effect of trying to close this socket.
*/
ps->defer_close = TRUE;
plug_receive(ps->plug, 0, data, len);
bufchain_consume(&ps->inputdata, len);
ps->defer_close = FALSE;
if (ps->deferred_close) {
sk_handle_close((Socket)ps);
hs->defer_close = TRUE;
plug_receive(hs->plug, 0, data, len);
bufchain_consume(&hs->inputdata, len);
hs->defer_close = FALSE;
if (hs->deferred_close) {
sk_handle_close(&hs->sockvt);
return;
}
if (bufchain_size(&ps->inputdata) > 0) {
if (bufchain_size(&hs->inputdata) > 0) {
/*
* If there's still data in our buffer, stay in THAWING state,
* and reschedule ourself.
*/
queue_toplevel_callback(handle_socket_unfreeze, ps);
queue_toplevel_callback(handle_socket_unfreeze, hs);
} else {
/*
* Otherwise, we've successfully thawed!
*/
ps->frozen = UNFROZEN;
handle_unthrottle(ps->recv_h, 0);
hs->frozen = UNFROZEN;
handle_unthrottle(hs->recv_h, 0);
}
}
static void sk_handle_set_frozen(Socket s, int is_frozen)
{
Handle_Socket ps = (Handle_Socket) s;
HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt);
if (is_frozen) {
switch (ps->frozen) {
switch (hs->frozen) {
case FREEZING:
case FROZEN:
return; /* nothing to do */
@ -230,7 +227,7 @@ static void sk_handle_set_frozen(Socket s, int is_frozen)
* throttled, so just return to FROZEN state. The toplevel
* callback will notice and disable itself.
*/
ps->frozen = FROZEN;
hs->frozen = FROZEN;
break;
case UNFROZEN:
@ -238,11 +235,11 @@ static void sk_handle_set_frozen(Socket s, int is_frozen)
* The normal case. Go to FREEZING, and expect one more
* load of data from winhandl if we're unlucky.
*/
ps->frozen = FREEZING;
hs->frozen = FREEZING;
break;
}
} else {
switch (ps->frozen) {
switch (hs->frozen) {
case UNFROZEN:
case THAWING:
return; /* nothing to do */
@ -253,8 +250,8 @@ static void sk_handle_set_frozen(Socket s, int is_frozen)
* we were frozen, then we'll still be in this state and
* can just unfreeze in the trivial way.
*/
assert(bufchain_size(&ps->inputdata) == 0);
ps->frozen = UNFROZEN;
assert(bufchain_size(&hs->inputdata) == 0);
hs->frozen = UNFROZEN;
break;
case FROZEN:
@ -262,21 +259,21 @@ static void sk_handle_set_frozen(Socket s, int is_frozen)
* If we have buffered data, go to THAWING and start
* releasing it in top-level callbacks.
*/
ps->frozen = THAWING;
queue_toplevel_callback(handle_socket_unfreeze, ps);
hs->frozen = THAWING;
queue_toplevel_callback(handle_socket_unfreeze, hs);
}
}
}
static const char *sk_handle_socket_error(Socket s)
{
Handle_Socket ps = (Handle_Socket) s;
return ps->error;
HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt);
return hs->error;
}
static char *sk_handle_peer_info(Socket s)
{
Handle_Socket ps = (Handle_Socket) s;
HandleSocket *hs = FROMFIELD(s, HandleSocket, sockvt);
ULONG pid;
static HMODULE kernel32_module;
DECL_WINDOWS_FUNCTION(static, BOOL, GetNamedPipeClientProcessId,
@ -303,48 +300,48 @@ static char *sk_handle_peer_info(Socket s)
* to log what we can find out about the client end.
*/
if (p_GetNamedPipeClientProcessId &&
p_GetNamedPipeClientProcessId(ps->send_H, &pid))
p_GetNamedPipeClientProcessId(hs->send_H, &pid))
return dupprintf("process id %lu", (unsigned long)pid);
return NULL;
}
static const Socket_vtable HandleSocket_sockvt = {
sk_handle_plug,
sk_handle_close,
sk_handle_write,
sk_handle_write_oob,
sk_handle_write_eof,
sk_handle_flush,
sk_handle_set_frozen,
sk_handle_socket_error,
sk_handle_peer_info,
};
Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, HANDLE stderr_H,
Plug plug, int overlapped)
{
static const struct socket_function_table socket_fn_table = {
sk_handle_plug,
sk_handle_close,
sk_handle_write,
sk_handle_write_oob,
sk_handle_write_eof,
sk_handle_flush,
sk_handle_set_frozen,
sk_handle_socket_error,
sk_handle_peer_info,
};
Handle_Socket ret;
HandleSocket *hs;
int flags = (overlapped ? HANDLE_FLAG_OVERLAPPED : 0);
ret = snew(struct Socket_handle_tag);
ret->fn = &socket_fn_table;
ret->plug = plug;
ret->error = NULL;
ret->frozen = UNFROZEN;
bufchain_init(&ret->inputdata);
bufchain_init(&ret->stderrdata);
hs = snew(HandleSocket);
hs->sockvt = &HandleSocket_sockvt;
hs->plug = plug;
hs->error = NULL;
hs->frozen = UNFROZEN;
bufchain_init(&hs->inputdata);
bufchain_init(&hs->stderrdata);
ret->recv_H = recv_H;
ret->recv_h = handle_input_new(ret->recv_H, handle_gotdata, ret, flags);
ret->send_H = send_H;
ret->send_h = handle_output_new(ret->send_H, handle_sentdata, ret, flags);
ret->stderr_H = stderr_H;
if (ret->stderr_H)
ret->stderr_h = handle_input_new(ret->stderr_H, handle_stderr,
ret, flags);
hs->recv_H = recv_H;
hs->recv_h = handle_input_new(hs->recv_H, handle_gotdata, hs, flags);
hs->send_H = send_H;
hs->send_h = handle_output_new(hs->send_H, handle_sentdata, hs, flags);
hs->stderr_H = stderr_H;
if (hs->stderr_H)
hs->stderr_h = handle_input_new(hs->stderr_H, handle_stderr,
hs, flags);
ret->defer_close = ret->deferred_close = FALSE;
hs->defer_close = hs->deferred_close = FALSE;
return (Socket) ret;
return &hs->sockvt;
}

Просмотреть файл

@ -35,16 +35,6 @@ const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
#define ipv4_is_loopback(addr) \
((p_ntohl(addr.s_addr) & 0xFF000000L) == 0x7F000000L)
/*
* We used to typedef struct Socket_tag *Socket.
*
* Since we have made the networking abstraction slightly more
* abstract, Socket no longer means a tcp socket (it could mean
* an ssl socket). So now we must use Actual_Socket when we know
* we are talking about a tcp socket.
*/
typedef struct Socket_tag *Actual_Socket;
/*
* Mutable state that goes with a SockAddr: stores information
* about where in the list of candidate IP(v*) addresses we've
@ -58,9 +48,8 @@ struct SockAddrStep_tag {
int curraddr;
};
struct Socket_tag {
const struct socket_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
typedef struct NetSocket NetSocket;
struct NetSocket {
const char *error;
SOCKET s;
Plug plug;
@ -85,7 +74,9 @@ struct Socket_tag {
* example. So here we define `parent' and `child' pointers to
* track this link.
*/
Actual_Socket parent, child;
NetSocket *parent, *child;
const Socket_vtable *sockvt;
};
struct SockAddr_tag {
@ -133,7 +124,7 @@ static tree234 *sktree;
static int cmpfortree(void *av, void *bv)
{
Actual_Socket a = (Actual_Socket) av, b = (Actual_Socket) bv;
NetSocket *a = (NetSocket *)av, *b = (NetSocket *)bv;
unsigned long as = (unsigned long) a->s, bs = (unsigned long) b->s;
if (as < bs)
return -1;
@ -148,7 +139,7 @@ static int cmpfortree(void *av, void *bv)
static int cmpforsearch(void *av, void *bv)
{
Actual_Socket b = (Actual_Socket) bv;
NetSocket *b = (NetSocket *)bv;
uintptr_t as = (uintptr_t) av, bs = (uintptr_t) b->s;
if (as < bs)
return -1;
@ -310,7 +301,7 @@ void sk_init(void)
GET_WINDOWS_FUNCTION(winsock_module, htonl);
GET_WINDOWS_FUNCTION(winsock_module, htons);
GET_WINDOWS_FUNCTION(winsock_module, ntohs);
GET_WINDOWS_FUNCTION(winsock_module, gethostname);
GET_WINDOWS_FUNCTION_NO_TYPECHECK(winsock_module, gethostname);
#else
/* The toolchain I use for Windows Coverity builds doesn't know
* the type signatures of these */
@ -356,7 +347,7 @@ void sk_init(void)
void sk_cleanup(void)
{
Actual_Socket s;
NetSocket *s;
int i;
if (sktree) {
@ -913,16 +904,16 @@ SockAddr sk_addr_dup(SockAddr addr)
return addr;
}
static Plug sk_tcp_plug(Socket sock, Plug p)
static Plug sk_net_plug(Socket sock, Plug p)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
Plug ret = s->plug;
if (p)
s->plug = p;
return ret;
}
static void sk_tcp_flush(Socket s)
static void sk_net_flush(Socket s)
{
/*
* We send data to the socket as soon as we can anyway,
@ -930,39 +921,39 @@ static void sk_tcp_flush(Socket s)
*/
}
static void sk_tcp_close(Socket s);
static int sk_tcp_write(Socket s, const void *data, int len);
static int sk_tcp_write_oob(Socket s, const void *data, int len);
static void sk_tcp_write_eof(Socket s);
static void sk_tcp_set_frozen(Socket s, int is_frozen);
static const char *sk_tcp_socket_error(Socket s);
static char *sk_tcp_peer_info(Socket s);
static void sk_net_close(Socket s);
static int sk_net_write(Socket s, const void *data, int len);
static int sk_net_write_oob(Socket s, const void *data, int len);
static void sk_net_write_eof(Socket s);
static void sk_net_set_frozen(Socket s, int is_frozen);
static const char *sk_net_socket_error(Socket s);
static char *sk_net_peer_info(Socket s);
extern char *do_select(SOCKET skt, int startup);
static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug)
{
static const struct socket_function_table fn_table = {
sk_tcp_plug,
sk_tcp_close,
sk_tcp_write,
sk_tcp_write_oob,
sk_tcp_write_eof,
sk_tcp_flush,
sk_tcp_set_frozen,
sk_tcp_socket_error,
sk_tcp_peer_info,
};
static const Socket_vtable NetSocket_sockvt = {
sk_net_plug,
sk_net_close,
sk_net_write,
sk_net_write_oob,
sk_net_write_eof,
sk_net_flush,
sk_net_set_frozen,
sk_net_socket_error,
sk_net_peer_info,
};
static Socket sk_net_accept(accept_ctx_t ctx, Plug plug)
{
DWORD err;
char *errstr;
Actual_Socket ret;
NetSocket *ret;
/*
* Create Socket structure.
* Create NetSocket structure.
*/
ret = snew(struct Socket_tag);
ret->fn = &fn_table;
ret = snew(NetSocket);
ret->sockvt = &NetSocket_sockvt;
ret->error = NULL;
ret->plug = plug;
bufchain_init(&ret->output_data);
@ -981,7 +972,7 @@ static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug)
if (ret->s == INVALID_SOCKET) {
err = p_WSAGetLastError();
ret->error = winsock_error_string(err);
return (Socket) ret;
return &ret->sockvt;
}
ret->oobinline = 0;
@ -991,15 +982,15 @@ static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug)
errstr = do_select(ret->s, 1);
if (errstr) {
ret->error = errstr;
return (Socket) ret;
return &ret->sockvt;
}
add234(sktree, ret);
return (Socket) ret;
return &ret->sockvt;
}
static DWORD try_connect(Actual_Socket sock)
static DWORD try_connect(NetSocket *sock)
{
SOCKET s;
#ifndef NO_IPV6
@ -1200,26 +1191,14 @@ static DWORD try_connect(Actual_Socket sock)
Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
int nodelay, int keepalive, Plug plug)
{
static const struct socket_function_table fn_table = {
sk_tcp_plug,
sk_tcp_close,
sk_tcp_write,
sk_tcp_write_oob,
sk_tcp_write_eof,
sk_tcp_flush,
sk_tcp_set_frozen,
sk_tcp_socket_error,
sk_tcp_peer_info,
};
Actual_Socket ret;
NetSocket *ret;
DWORD err;
/*
* Create Socket structure.
* Create NetSocket structure.
*/
ret = snew(struct Socket_tag);
ret->fn = &fn_table;
ret = snew(NetSocket);
ret->sockvt = &NetSocket_sockvt;
ret->error = NULL;
ret->plug = plug;
bufchain_init(&ret->output_data);
@ -1246,24 +1225,12 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
err = try_connect(ret);
} while (err && sk_nextaddr(ret->addr, &ret->step));
return (Socket) ret;
return &ret->sockvt;
}
Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
int local_host_only, int orig_address_family)
{
static const struct socket_function_table fn_table = {
sk_tcp_plug,
sk_tcp_close,
sk_tcp_write,
sk_tcp_write_oob,
sk_tcp_write_eof,
sk_tcp_flush,
sk_tcp_set_frozen,
sk_tcp_socket_error,
sk_tcp_peer_info,
};
SOCKET s;
#ifndef NO_IPV6
SOCKADDR_IN6 a6;
@ -1272,17 +1239,17 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
DWORD err;
char *errstr;
Actual_Socket ret;
NetSocket *ret;
int retcode;
int on = 1;
int address_family;
/*
* Create Socket structure.
* Create NetSocket structure.
*/
ret = snew(struct Socket_tag);
ret->fn = &fn_table;
ret = snew(NetSocket);
ret->sockvt = &NetSocket_sockvt;
ret->error = NULL;
ret->plug = plug;
bufchain_init(&ret->output_data);
@ -1324,10 +1291,10 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
if (s == INVALID_SOCKET) {
err = p_WSAGetLastError();
ret->error = winsock_error_string(err);
return (Socket) ret;
return &ret->sockvt;
}
SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0);
SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0);
ret->oobinline = 0;
@ -1410,14 +1377,14 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
if (err) {
p_closesocket(s);
ret->error = winsock_error_string(err);
return (Socket) ret;
return &ret->sockvt;
}
if (p_listen(s, SOMAXCONN) == SOCKET_ERROR) {
p_closesocket(s);
ret->error = winsock_error_string(p_WSAGetLastError());
return (Socket) ret;
return &ret->sockvt;
}
/* Set up a select mechanism. This could be an AsyncSelect on a
@ -1426,7 +1393,7 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
if (errstr) {
p_closesocket(s);
ret->error = errstr;
return (Socket) ret;
return &ret->sockvt;
}
add234(sktree, ret);
@ -1437,32 +1404,31 @@ Socket sk_newlistener(const char *srcaddr, int port, Plug plug,
* IPv6 listening socket and link it to this one.
*/
if (address_family == AF_INET && orig_address_family == ADDRTYPE_UNSPEC) {
Actual_Socket other;
other = (Actual_Socket) sk_newlistener(srcaddr, port, plug,
local_host_only, ADDRTYPE_IPV6);
Socket other = sk_newlistener(srcaddr, port, plug,
local_host_only, ADDRTYPE_IPV6);
if (other) {
if (!other->error) {
other->parent = ret;
ret->child = other;
NetSocket *ns = FROMFIELD(other, NetSocket, sockvt);
if (!ns->error) {
ns->parent = ret;
ret->child = ns;
} else {
sfree(other);
sfree(ns);
}
}
}
#endif
return (Socket) ret;
return &ret->sockvt;
}
static void sk_tcp_close(Socket sock)
static void sk_net_close(Socket sock)
{
extern char *do_select(SOCKET skt, int startup);
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
if (s->child)
sk_tcp_close((Socket)s->child);
sk_net_close(&s->child->sockvt);
del234(sktree, s);
do_select(s->s, 0);
@ -1477,7 +1443,7 @@ static void sk_tcp_close(Socket sock)
*/
static void socket_error_callback(void *vs)
{
Actual_Socket s = (Actual_Socket)vs;
NetSocket *s = (NetSocket *)vs;
/*
* Just in case other socket work has caused this socket to vanish
@ -1497,7 +1463,7 @@ static void socket_error_callback(void *vs)
* The function which tries to send on a socket once it's deemed
* writable.
*/
void try_send(Actual_Socket s)
void try_send(NetSocket *s)
{
while (s->sending_oob || bufchain_size(&s->output_data) > 0) {
int nsent;
@ -1568,9 +1534,9 @@ void try_send(Actual_Socket s)
}
}
static int sk_tcp_write(Socket sock, const void *buf, int len)
static int sk_net_write(Socket sock, const void *buf, int len)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
assert(s->outgoingeof == EOF_NO);
@ -1588,9 +1554,9 @@ static int sk_tcp_write(Socket sock, const void *buf, int len)
return bufchain_size(&s->output_data);
}
static int sk_tcp_write_oob(Socket sock, const void *buf, int len)
static int sk_net_write_oob(Socket sock, const void *buf, int len)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
assert(s->outgoingeof == EOF_NO);
@ -1611,9 +1577,9 @@ static int sk_tcp_write_oob(Socket sock, const void *buf, int len)
return s->sending_oob;
}
static void sk_tcp_write_eof(Socket sock)
static void sk_net_write_eof(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
assert(s->outgoingeof == EOF_NO);
@ -1634,7 +1600,7 @@ void select_result(WPARAM wParam, LPARAM lParam)
int ret;
DWORD err;
char buf[20480]; /* nice big buffer for plenty of speed */
Actual_Socket s;
NetSocket *s;
u_long atmark;
/* wParam is the socket itself */
@ -1798,7 +1764,7 @@ void select_result(WPARAM wParam, LPARAM lParam)
#endif
{
p_closesocket(t); /* dodgy WinSock let nonlocal through */
} else if (plug_accepting(s->plug, sk_tcp_accept, actx)) {
} else if (plug_accepting(s->plug, sk_net_accept, actx)) {
p_closesocket(t); /* denied or error */
}
}
@ -1814,15 +1780,15 @@ const char *sk_addr_error(SockAddr addr)
{
return addr->error;
}
static const char *sk_tcp_socket_error(Socket sock)
static const char *sk_net_socket_error(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
return s->error;
}
static char *sk_tcp_peer_info(Socket sock)
static char *sk_net_peer_info(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
#ifdef NO_IPV6
struct sockaddr_in addr;
#else
@ -1852,9 +1818,9 @@ static char *sk_tcp_peer_info(Socket sock)
}
}
static void sk_tcp_set_frozen(Socket sock, int is_frozen)
static void sk_net_set_frozen(Socket sock, int is_frozen)
{
Actual_Socket s = (Actual_Socket) sock;
NetSocket *s = FROMFIELD(sock, NetSocket, sockvt);
if (s->frozen == is_frozen)
return;
s->frozen = is_frozen;
@ -1870,7 +1836,7 @@ static void sk_tcp_set_frozen(Socket sock, int is_frozen)
void socket_reselect_all(void)
{
Actual_Socket s;
NetSocket *s;
int i;
for (i = 0; (s = index234(sktree, i)) != NULL; i++) {
@ -1884,7 +1850,7 @@ void socket_reselect_all(void)
*/
SOCKET first_socket(int *state)
{
Actual_Socket s;
NetSocket *s;
*state = 0;
s = index234(sktree, (*state)++);
return s ? s->s : INVALID_SOCKET;
@ -1892,13 +1858,13 @@ SOCKET first_socket(int *state)
SOCKET next_socket(int *state)
{
Actual_Socket s = index234(sktree, (*state)++);
NetSocket *s = index234(sktree, (*state)++);
return s ? s->s : INVALID_SOCKET;
}
extern int socket_writable(SOCKET skt)
{
Actual_Socket s = find234(sktree, (void *)skt, cmpforsearch);
NetSocket *s = find234(sktree, (void *)skt, cmpforsearch);
if (s)
return bufchain_size(&s->output_data) > 0;

Просмотреть файл

@ -19,11 +19,7 @@
Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, HANDLE stderr_H,
Plug plug, int overlapped);
typedef struct Socket_named_pipe_server_tag *Named_Pipe_Server_Socket;
struct Socket_named_pipe_server_tag {
const struct socket_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
typedef struct NamedPipeServerSocket {
/* Parameters for (repeated) creation of named pipe objects */
PSECURITY_DESCRIPTOR psd;
PACL acl;
@ -37,11 +33,13 @@ struct Socket_named_pipe_server_tag {
/* PuTTY Socket machinery */
Plug plug;
char *error;
};
const Socket_vtable *sockvt;
} NamedPipeServerSocket;
static Plug sk_namedpipeserver_plug(Socket s, Plug p)
{
Named_Pipe_Server_Socket ps = (Named_Pipe_Server_Socket) s;
NamedPipeServerSocket *ps = FROMFIELD(s, NamedPipeServerSocket, sockvt);
Plug ret = ps->plug;
if (p)
ps->plug = p;
@ -50,7 +48,7 @@ static Plug sk_namedpipeserver_plug(Socket s, Plug p)
static void sk_namedpipeserver_close(Socket s)
{
Named_Pipe_Server_Socket ps = (Named_Pipe_Server_Socket) s;
NamedPipeServerSocket *ps = FROMFIELD(s, NamedPipeServerSocket, sockvt);
if (ps->callback_handle)
handle_free(ps->callback_handle);
@ -67,7 +65,7 @@ static void sk_namedpipeserver_close(Socket s)
static const char *sk_namedpipeserver_socket_error(Socket s)
{
Named_Pipe_Server_Socket ps = (Named_Pipe_Server_Socket) s;
NamedPipeServerSocket *ps = FROMFIELD(s, NamedPipeServerSocket, sockvt);
return ps->error;
}
@ -76,7 +74,7 @@ static char *sk_namedpipeserver_peer_info(Socket s)
return NULL;
}
static int create_named_pipe(Named_Pipe_Server_Socket ps, int first_instance)
static int create_named_pipe(NamedPipeServerSocket *ps, int first_instance)
{
SECURITY_ATTRIBUTES sa;
@ -129,7 +127,7 @@ static Socket named_pipe_accept(accept_ctx_t ctx, Plug plug)
*/
SockAddr sk_namedpipe_addr(const char *pipename);
static void named_pipe_accept_loop(Named_Pipe_Server_Socket ps,
static void named_pipe_accept_loop(NamedPipeServerSocket *ps,
int got_one_already)
{
while (1) {
@ -198,32 +196,30 @@ static void named_pipe_accept_loop(Named_Pipe_Server_Socket ps,
static void named_pipe_connect_callback(void *vps)
{
Named_Pipe_Server_Socket ps = (Named_Pipe_Server_Socket)vps;
NamedPipeServerSocket *ps = (NamedPipeServerSocket *)vps;
named_pipe_accept_loop(ps, TRUE);
}
/*
* This socket type is only used for listening, so it should never
* be asked to write or flush or set_frozen.
*/
static const Socket_vtable NamedPipeServerSocket_sockvt = {
sk_namedpipeserver_plug,
sk_namedpipeserver_close,
NULL /* write */,
NULL /* write_oob */,
NULL /* write_eof */,
NULL /* flush */,
NULL /* set_frozen */,
sk_namedpipeserver_socket_error,
sk_namedpipeserver_peer_info,
};
Socket new_named_pipe_listener(const char *pipename, Plug plug)
{
/*
* This socket type is only used for listening, so it should never
* be asked to write or flush or set_frozen.
*/
static const struct socket_function_table socket_fn_table = {
sk_namedpipeserver_plug,
sk_namedpipeserver_close,
NULL /* write */,
NULL /* write_oob */,
NULL /* write_eof */,
NULL /* flush */,
NULL /* set_frozen */,
sk_namedpipeserver_socket_error,
sk_namedpipeserver_peer_info,
};
Named_Pipe_Server_Socket ret;
ret = snew(struct Socket_named_pipe_server_tag);
ret->fn = &socket_fn_table;
NamedPipeServerSocket *ret = snew(NamedPipeServerSocket);
ret->sockvt = &NamedPipeServerSocket_sockvt;
ret->plug = plug;
ret->error = NULL;
ret->psd = NULL;
@ -253,7 +249,7 @@ Socket new_named_pipe_listener(const char *pipename, Plug plug)
named_pipe_accept_loop(ret, FALSE);
cleanup:
return (Socket) ret;
return &ret->sockvt;
}
#endif /* !defined NO_SECURITY */

Просмотреть файл

@ -27,8 +27,6 @@ struct XDMSeen {
};
struct X11Connection {
const struct plug_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */
unsigned char firstpkt[12]; /* first X data packet */
tree234 *authtree;
struct X11Display *disp;
@ -42,6 +40,8 @@ struct X11Connection {
int peer_port;
struct ssh_channel *c; /* channel structure held by ssh.c */
Socket s;
const Plug_vtable *plugvt;
};
static int xdmseen_cmp(void *a, void *b)
@ -63,7 +63,7 @@ static void dummy_plug_closing
static void dummy_plug_receive(Plug p, int urgent, char *data, int len) { }
static void dummy_plug_sent(Plug p, int bufsize) { }
static int dummy_plug_accepting(Plug p, accept_fn_t constructor, accept_ctx_t ctx) { return 1; }
static const struct plug_function_table dummy_plug = {
static const Plug_vtable dummy_plug_vtable = {
dummy_plug_log, dummy_plug_closing, dummy_plug_receive,
dummy_plug_sent, dummy_plug_accepting
};
@ -306,8 +306,8 @@ struct X11Display *x11_setup_display(const char *display, Conf *conf)
if (!err) {
/* Create trial connection to see if there is a useful Unix-domain
* socket */
const struct plug_function_table *dummy = &dummy_plug;
Socket s = sk_new(sk_addr_dup(ux), 0, 0, 0, 0, 0, (Plug)&dummy);
const Plug_vtable *dummy = &dummy_plug_vtable;
Socket s = sk_new(sk_addr_dup(ux), 0, 0, 0, 0, 0, &dummy);
err = sk_socket_error(s);
sk_close(s);
}
@ -617,7 +617,8 @@ static void x11_send_init_error(struct X11Connection *conn,
static void x11_closing(Plug plug, const char *error_msg, int error_code,
int calling_back)
{
struct X11Connection *xconn = (struct X11Connection *) plug;
struct X11Connection *xconn = FROMFIELD(
plug, struct X11Connection, plugvt);
if (error_msg) {
/*
@ -648,7 +649,8 @@ static void x11_closing(Plug plug, const char *error_msg, int error_code,
static void x11_receive(Plug plug, int urgent, char *data, int len)
{
struct X11Connection *xconn = (struct X11Connection *) plug;
struct X11Connection *xconn = FROMFIELD(
plug, struct X11Connection, plugvt);
if (sshfwd_write(xconn->c, data, len) > 0) {
xconn->throttled = 1;
@ -659,7 +661,8 @@ static void x11_receive(Plug plug, int urgent, char *data, int len)
static void x11_sent(Plug plug, int bufsize)
{
struct X11Connection *xconn = (struct X11Connection *) plug;
struct X11Connection *xconn = FROMFIELD(
plug, struct X11Connection, plugvt);
sshfwd_unthrottle(xconn->c, bufsize);
}
@ -682,6 +685,14 @@ int x11_get_screen_number(char *display)
return atoi(display + n + 1);
}
static const Plug_vtable X11Connection_plugvt = {
x11_log,
x11_closing,
x11_receive,
x11_sent,
NULL
};
/*
* Called to set up the X11Connection structure, though this does not
* yet connect to an actual server.
@ -689,21 +700,13 @@ int x11_get_screen_number(char *display)
struct X11Connection *x11_init(tree234 *authtree, void *c,
const char *peeraddr, int peerport)
{
static const struct plug_function_table fn_table = {
x11_log,
x11_closing,
x11_receive,
x11_sent,
NULL
};
struct X11Connection *xconn;
/*
* Open socket.
*/
xconn = snew(struct X11Connection);
xconn->fn = &fn_table;
xconn->plugvt = &X11Connection_plugvt;
xconn->auth_protocol = NULL;
xconn->authtree = authtree;
xconn->verified = 0;
@ -914,7 +917,7 @@ int x11_send(struct X11Connection *xconn, char *data, int len)
xconn->disp = auth_matched->disp;
xconn->s = new_connection(sk_addr_dup(xconn->disp->addr),
xconn->disp->realhost, xconn->disp->port,
0, 1, 0, 0, (Plug) xconn,
0, 1, 0, 0, &xconn->plugvt,
sshfwd_get_conf(xconn->c));
if ((err = sk_socket_error(xconn->s)) != NULL) {
char *err_message = dupprintf("unable to connect to"