diff --git a/cproxy.c b/cproxy.c index dedfef2a..142c2a17 100644 --- a/cproxy.c +++ b/cproxy.c @@ -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); diff --git a/defs.h b/defs.h index 27062774..3946e1ed 100644 --- a/defs.h +++ b/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 diff --git a/errsock.c b/errsock.c index 854fd8be..824cd6e8 100644 --- a/errsock.c +++ b/errsock.c @@ -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; } diff --git a/network.h b/network.h index 680d3f04..438d6013 100644 --- a/network.h +++ b/network.h @@ -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); /* diff --git a/nocproxy.c b/nocproxy.c index 759724b7..26d75a7e 100644 --- a/nocproxy.c +++ b/nocproxy.c @@ -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", diff --git a/pageant.c b/pageant.c index 2a62dfd0..357fdc67 100644 --- a/pageant.c +++ b/pageant.c @@ -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; } diff --git a/pageant.h b/pageant.h index cb929751..551c2a36 100644 --- a/pageant.h +++ b/pageant.h @@ -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); diff --git a/portfwd.c b/portfwd.c index 80c2f4b4..d27abb41 100644 --- a/portfwd.c +++ b/portfwd.c @@ -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) { diff --git a/proxy.c b/proxy.c index 3fe36e12..6ccd4025 100644 --- a/proxy.c +++ b/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; diff --git a/proxy.h b/proxy.h index da0b9ed9..1fae25d2 100644 --- a/proxy.h +++ b/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 diff --git a/raw.c b/raw.c index 47454de0..67d34601 100644 --- a/raw.c +++ b/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; diff --git a/rlogin.c b/rlogin.c index 92660b86..9156340c 100644 --- a/rlogin.c +++ b/rlogin.c @@ -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; diff --git a/ssh.c b/ssh.c index b84a7cef..912994ff 100644 --- a/ssh.c +++ b/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); } diff --git a/ssh.h b/ssh.h index 825b4674..7537361e 100644 --- a/ssh.h +++ b/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); diff --git a/sshshare.c b/sshshare.c index 6c49b941..aa2313e1 100644 --- a/sshshare.c +++ b/sshshare.c @@ -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); diff --git a/telnet.c b/telnet.c index eaaa48c7..6fe509dc 100644 --- a/telnet.c +++ b/telnet.c @@ -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; diff --git a/unix/unix.h b/unix/unix.h index 87ff6ea3..14ce470a 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -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 diff --git a/unix/uxnet.c b/unix/uxnet.c index 66fa208a..e13b9485 100644 --- a/unix/uxnet.c +++ b/unix/uxnet.c @@ -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; } diff --git a/unix/uxpgnt.c b/unix/uxpgnt.c index 277d31d2..4ef4d433 100644 --- a/unix/uxpgnt.c +++ b/unix/uxpgnt.c @@ -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); diff --git a/unix/uxproxy.c b/unix/uxproxy.c index 95426e3e..74be9b2d 100644 --- a/unix/uxproxy.c +++ b/unix/uxproxy.c @@ -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; } diff --git a/windows/winhsock.c b/windows/winhsock.c index 9b725332..c7c833e2 100644 --- a/windows/winhsock.c +++ b/windows/winhsock.c @@ -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; } diff --git a/windows/winnet.c b/windows/winnet.c index 3f2fe4cc..ac2eae27 100644 --- a/windows/winnet.c +++ b/windows/winnet.c @@ -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; diff --git a/windows/winnps.c b/windows/winnps.c index f992a4f0..ff71b0a4 100644 --- a/windows/winnps.c +++ b/windows/winnps.c @@ -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 */ diff --git a/x11fwd.c b/x11fwd.c index 1f499e9c..45b959a7 100644 --- a/x11fwd.c +++ b/x11fwd.c @@ -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"