mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 01:48:00 +00:00
Dave Hinton's modifications to the network layer interface, which
should make it possible to add SSL support later. [originally from svn r996]
This commit is contained in:
parent
40a68abec5
commit
7b0e082700
126
network.h
126
network.h
@ -3,52 +3,78 @@
|
|||||||
*
|
*
|
||||||
* The way this works is: a back end can choose to open any number
|
* The way this works is: a back end can choose to open any number
|
||||||
* of sockets - including zero, which might be necessary in some.
|
* of sockets - including zero, which might be necessary in some.
|
||||||
* It can register a function to be called when data comes in on
|
* It can register a bunch of callbacks (most notably for when
|
||||||
* any given one, and it can call the networking abstraction to
|
* data is received) for each socket, and it can call the networking
|
||||||
* send data without having to worry about blocking. The stuff
|
* abstraction to send data without having to worry about blocking.
|
||||||
* behind the abstraction takes care of selects and nonblocking
|
* The stuff behind the abstraction takes care of selects and
|
||||||
* writes and all that sort of painful gubbins.
|
* nonblocking writes and all that sort of painful gubbins.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef PUTTY_NETWORK_H
|
#ifndef PUTTY_NETWORK_H
|
||||||
#define PUTTY_NETWORK_H
|
#define PUTTY_NETWORK_H
|
||||||
|
|
||||||
typedef struct Socket_tag *Socket;
|
|
||||||
typedef struct SockAddr_tag *SockAddr;
|
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 {
|
||||||
|
Plug (*plug) (Socket s, Plug p);
|
||||||
|
/* use a different plug (return the old one) */
|
||||||
|
/* if p is NULL, it doesn't change the plug */
|
||||||
|
/* but it does return the one it's using */
|
||||||
|
void (*close) (Socket s);
|
||||||
|
void (*write) (Socket s, char *data, int len);
|
||||||
|
void (*write_oob) (Socket s, char *data, int len);
|
||||||
|
void (*flush) (Socket s);
|
||||||
|
/* ignored by tcp, but vital for ssl */
|
||||||
|
char *(*socket_error) (Socket s);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct plug_function_table {
|
||||||
|
int (*closing)
|
||||||
|
(Plug p, char *error_msg, int error_code, int calling_back);
|
||||||
|
/* error_msg is NULL iff it is not an error (ie it closed normally) */
|
||||||
|
/* calling_back != 0 iff there is a Plug function */
|
||||||
|
/* currently running (would cure the fixme in try_send()) */
|
||||||
|
int (*receive) (Plug p, int urgent, char *data, int len);
|
||||||
|
/*
|
||||||
|
* - urgent==0. `data' points to `len' bytes of perfectly
|
||||||
|
* ordinary data.
|
||||||
|
*
|
||||||
|
* - urgent==1. `data' points to `len' bytes of data,
|
||||||
|
* which were read from before an Urgent pointer.
|
||||||
|
*
|
||||||
|
* - urgent==2. `data' points to `len' bytes of data,
|
||||||
|
* the first of which was the one at the Urgent mark.
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* This is the function a client must register with each socket, to
|
|
||||||
* receive data coming in on that socket. The parameter `urgent'
|
|
||||||
* decides the meaning of `data' and `len':
|
|
||||||
*
|
|
||||||
* - urgent==0. `data' points to `len' bytes of perfectly ordinary
|
|
||||||
* data.
|
|
||||||
*
|
|
||||||
* - urgent==1. `data' points to `len' bytes of data, which were
|
|
||||||
* read from before an Urgent pointer.
|
|
||||||
*
|
|
||||||
* - urgent==2. `data' points to `len' bytes of data, the first of
|
|
||||||
* which was the one at the Urgent mark.
|
|
||||||
*
|
|
||||||
* - urgent==3. An error has occurred on the socket. `data' points
|
|
||||||
* to an error string, and `len' points to an error code.
|
|
||||||
*/
|
|
||||||
typedef int (*sk_receiver_t)(Socket s, int urgent, char *data, int len);
|
|
||||||
|
|
||||||
void sk_init(void); /* called once at program startup */
|
void sk_init(void); /* called once at program startup */
|
||||||
|
|
||||||
SockAddr sk_namelookup(char *host, char **canonicalname);
|
SockAddr sk_namelookup(char *host, char **canonicalname);
|
||||||
void sk_addr_free(SockAddr addr);
|
void sk_addr_free(SockAddr addr);
|
||||||
|
|
||||||
Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
Socket sk_new(SockAddr addr, int port, int privport, int oobinline, Plug p);
|
||||||
sk_receiver_t receiver);
|
|
||||||
void sk_close(Socket s);
|
#define sk_plug(s,p) (((*s)->plug) (s, p))
|
||||||
void sk_write(Socket s, char *buf, int len);
|
#define sk_close(s) (((*s)->close) (s))
|
||||||
void sk_write_oob(Socket s, char *buf, int len);
|
#define sk_write(s,buf,len) (((*s)->write) (s, buf, len))
|
||||||
|
#define sk_write_oob(s,buf,len) (((*s)->write_oob) (s, buf, len))
|
||||||
|
#define sk_flush(s) (((*s)->flush) (s))
|
||||||
|
|
||||||
|
#ifdef DEFINE_PLUG_METHOD_MACROS
|
||||||
|
#define plug_closing(p,msg,code,callback) (((*p)->closing) (p, msg, code, callback))
|
||||||
|
#define plug_receive(p,urgent,buf,len) (((*p)->receive) (p, urgent, buf, len))
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Each socket abstraction contains a `void *' private field in
|
* Each socket abstraction contains a `void *' private field in
|
||||||
* which the client can keep state.
|
* which the client can keep state.
|
||||||
|
*
|
||||||
|
* This is perhaps unnecessary now that we have the notion of a plug,
|
||||||
|
* but there is some existing code that uses it, so it stays.
|
||||||
*/
|
*/
|
||||||
void sk_set_private_ptr(Socket s, void *ptr);
|
void sk_set_private_ptr(Socket s, void *ptr);
|
||||||
void *sk_get_private_ptr(Socket s);
|
void *sk_get_private_ptr(Socket s);
|
||||||
@ -59,6 +85,46 @@ void *sk_get_private_ptr(Socket s);
|
|||||||
* or return NULL if there's no problem.
|
* or return NULL if there's no problem.
|
||||||
*/
|
*/
|
||||||
char *sk_addr_error(SockAddr addr);
|
char *sk_addr_error(SockAddr addr);
|
||||||
char *sk_socket_error(Socket addr);
|
#define sk_socket_error(s) (((*s)->socket_error) (s))
|
||||||
|
|
||||||
|
|
||||||
|
/********** SSL stuff **********/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This section is subject to change, but you get the general idea
|
||||||
|
* of what it will eventually look like.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct certificate *Certificate;
|
||||||
|
typedef struct our_certificate *Our_Certificate;
|
||||||
|
/* to be defined somewhere else, somehow */
|
||||||
|
|
||||||
|
typedef struct ssl_client_socket_function_table **SSL_Client_Socket;
|
||||||
|
typedef struct ssl_client_plug_function_table **SSL_Client_Plug;
|
||||||
|
|
||||||
|
struct ssl_client_socket_function_table {
|
||||||
|
struct socket_function_table base;
|
||||||
|
void (*renegotiate) (SSL_Client_Socket s);
|
||||||
|
/* renegotiate the cipher spec */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ssl_client_plug_function_table {
|
||||||
|
struct plug_function_table base;
|
||||||
|
int (*refuse_cert) (SSL_Client_Plug p, Certificate cert[]);
|
||||||
|
/* do we accept this certificate chain? If not, why not? */
|
||||||
|
/* cert[0] is the server's certificate, cert[] is NULL-terminated */
|
||||||
|
/* the last certificate may or may not be the root certificate */
|
||||||
|
Our_Certificate (*client_cert) (SSL_Client_Plug p);
|
||||||
|
/* the server wants us to identify ourselves */
|
||||||
|
/* may return NULL if we want anonymity */
|
||||||
|
};
|
||||||
|
|
||||||
|
SSL_Client_Socket sk_ssl_client_over (
|
||||||
|
Socket s, /* pre-existing (tcp) connection */
|
||||||
|
SSL_Client_Plug p
|
||||||
|
);
|
||||||
|
|
||||||
|
#define sk_renegotiate(s) (((*s)->renegotiate) (s))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
30
raw.c
30
raw.c
@ -24,20 +24,17 @@ static void c_write (char *buf, int len) {
|
|||||||
from_backend(0, buf, len);
|
from_backend(0, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int raw_receive (Socket skt, int urgent, char *data, int len) {
|
static int raw_closing (Plug plug, char *error_msg, int error_code, int calling_back) {
|
||||||
if (urgent==3) {
|
sk_close(s);
|
||||||
|
s = NULL;
|
||||||
|
if (error_msg) {
|
||||||
/* A socket error has occurred. */
|
/* A socket error has occurred. */
|
||||||
sk_close(s);
|
connection_fatal (error_msg);
|
||||||
s = NULL;
|
} /* Otherwise, the remote side closed the connection normally. */
|
||||||
connection_fatal(data);
|
return 0;
|
||||||
len = 0;
|
}
|
||||||
return 0;
|
|
||||||
} else if (!len) {
|
static int raw_receive (Plug plug, int urgent, char *data, int len) {
|
||||||
/* Connection has closed. */
|
|
||||||
sk_close(s);
|
|
||||||
s = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
c_write(data, len);
|
c_write(data, len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -50,6 +47,11 @@ static int raw_receive (Socket skt, int urgent, char *data, int len) {
|
|||||||
* Also places the canonical host name into `realhost'.
|
* Also places the canonical host name into `realhost'.
|
||||||
*/
|
*/
|
||||||
static char *raw_init (char *host, int port, char **realhost) {
|
static char *raw_init (char *host, int port, char **realhost) {
|
||||||
|
static struct plug_function_table fn_table = {
|
||||||
|
raw_closing,
|
||||||
|
raw_receive
|
||||||
|
}, *fn_table_ptr = &fn_table;
|
||||||
|
|
||||||
SockAddr addr;
|
SockAddr addr;
|
||||||
char *err;
|
char *err;
|
||||||
|
|
||||||
@ -66,7 +68,7 @@ static char *raw_init (char *host, int port, char **realhost) {
|
|||||||
/*
|
/*
|
||||||
* Open socket.
|
* Open socket.
|
||||||
*/
|
*/
|
||||||
s = sk_new(addr, port, 0, 1, raw_receive);
|
s = sk_new(addr, port, 0, 1, &fn_table_ptr);
|
||||||
if ( (err = sk_socket_error(s)) )
|
if ( (err = sk_socket_error(s)) )
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
29
rlogin.c
29
rlogin.c
@ -25,19 +25,17 @@ static void c_write (char *buf, int len) {
|
|||||||
from_backend(0, buf, len);
|
from_backend(0, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rlogin_receive (Socket skt, int urgent, char *data, int len) {
|
static int rlogin_closing (Plug plug, char *error_msg, int error_code, int calling_back) {
|
||||||
if (urgent==3) {
|
sk_close(s);
|
||||||
|
s = NULL;
|
||||||
|
if (error_msg) {
|
||||||
/* A socket error has occurred. */
|
/* A socket error has occurred. */
|
||||||
sk_close(s);
|
connection_fatal (error_msg);
|
||||||
s = NULL;
|
} /* Otherwise, the remote side closed the connection normally. */
|
||||||
connection_fatal(data);
|
return 0;
|
||||||
return 0;
|
}
|
||||||
} else if (!len) {
|
|
||||||
/* Connection has closed. */
|
static int rlogin_receive (Plug plug, int urgent, char *data, int len) {
|
||||||
sk_close(s);
|
|
||||||
s = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (urgent == 2) {
|
if (urgent == 2) {
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
@ -77,6 +75,11 @@ static int rlogin_receive (Socket skt, int urgent, char *data, int len) {
|
|||||||
* Also places the canonical host name into `realhost'.
|
* Also places the canonical host name into `realhost'.
|
||||||
*/
|
*/
|
||||||
static char *rlogin_init (char *host, int port, char **realhost) {
|
static char *rlogin_init (char *host, int port, char **realhost) {
|
||||||
|
static struct plug_function_table fn_table = {
|
||||||
|
rlogin_closing,
|
||||||
|
rlogin_receive
|
||||||
|
}, *fn_table_ptr = &fn_table;
|
||||||
|
|
||||||
SockAddr addr;
|
SockAddr addr;
|
||||||
char *err;
|
char *err;
|
||||||
|
|
||||||
@ -93,7 +96,7 @@ static char *rlogin_init (char *host, int port, char **realhost) {
|
|||||||
/*
|
/*
|
||||||
* Open socket.
|
* Open socket.
|
||||||
*/
|
*/
|
||||||
s = sk_new(addr, port, 1, 0, rlogin_receive);
|
s = sk_new(addr, port, 1, 0, &fn_table_ptr);
|
||||||
if ( (err = sk_socket_error(s)) )
|
if ( (err = sk_socket_error(s)) )
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
32
ssh.c
32
ssh.c
@ -1270,21 +1270,20 @@ static void ssh_gotdata(unsigned char *data, int datalen)
|
|||||||
crFinishV;
|
crFinishV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ssh_receive(Socket skt, int urgent, char *data, int len) {
|
static int ssh_closing (Plug plug, char *error_msg, int error_code, int calling_back) {
|
||||||
if (urgent==3) {
|
ssh_state = SSH_STATE_CLOSED;
|
||||||
|
sk_close(s);
|
||||||
|
s = NULL;
|
||||||
|
if (error_msg) {
|
||||||
/* A socket error has occurred. */
|
/* A socket error has occurred. */
|
||||||
ssh_state = SSH_STATE_CLOSED;
|
connection_fatal (error_msg);
|
||||||
sk_close(s);
|
} else {
|
||||||
s = NULL;
|
/* Otherwise, the remote side closed the connection normally. */
|
||||||
connection_fatal(data);
|
|
||||||
return 0;
|
|
||||||
} else if (!len) {
|
|
||||||
/* Connection has closed. */
|
|
||||||
ssh_state = SSH_STATE_CLOSED;
|
|
||||||
sk_close(s);
|
|
||||||
s = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ssh_receive(Plug plug, int urgent, char *data, int len) {
|
||||||
ssh_gotdata (data, len);
|
ssh_gotdata (data, len);
|
||||||
if (ssh_state == SSH_STATE_CLOSED) {
|
if (ssh_state == SSH_STATE_CLOSED) {
|
||||||
if (s) {
|
if (s) {
|
||||||
@ -1303,6 +1302,11 @@ static int ssh_receive(Socket skt, int urgent, char *data, int len) {
|
|||||||
*/
|
*/
|
||||||
static char *connect_to_host(char *host, int port, char **realhost)
|
static char *connect_to_host(char *host, int port, char **realhost)
|
||||||
{
|
{
|
||||||
|
static struct plug_function_table fn_table = {
|
||||||
|
ssh_closing,
|
||||||
|
ssh_receive
|
||||||
|
}, *fn_table_ptr = &fn_table;
|
||||||
|
|
||||||
SockAddr addr;
|
SockAddr addr;
|
||||||
char *err;
|
char *err;
|
||||||
#ifdef FWHACK
|
#ifdef FWHACK
|
||||||
@ -1340,7 +1344,7 @@ static char *connect_to_host(char *host, int port, char **realhost)
|
|||||||
/*
|
/*
|
||||||
* Open socket.
|
* Open socket.
|
||||||
*/
|
*/
|
||||||
s = sk_new(addr, port, 0, 1, ssh_receive);
|
s = sk_new(addr, port, 0, 1, &fn_table_ptr);
|
||||||
if ( (err = sk_socket_error(s)) )
|
if ( (err = sk_socket_error(s)) )
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
29
telnet.c
29
telnet.c
@ -465,19 +465,17 @@ static void do_telnet_read (char *buf, int len) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int telnet_receive(Socket skt, int urgent, char *data, int len) {
|
static int telnet_closing (Plug plug, char *error_msg, int error_code, int calling_back) {
|
||||||
if (urgent==3) {
|
sk_close(s);
|
||||||
|
s = NULL;
|
||||||
|
if (error_msg) {
|
||||||
/* A socket error has occurred. */
|
/* A socket error has occurred. */
|
||||||
sk_close(s);
|
connection_fatal (error_msg);
|
||||||
s = NULL;
|
} /* Otherwise, the remote side closed the connection normally. */
|
||||||
connection_fatal(data);
|
return 0;
|
||||||
return 0;
|
}
|
||||||
} else if (!len) {
|
|
||||||
/* Connection has closed. */
|
static int telnet_receive(Plug plug, int urgent, char *data, int len) {
|
||||||
sk_close(s);
|
|
||||||
s = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(urgent) in_synch = TRUE;
|
if(urgent) in_synch = TRUE;
|
||||||
do_telnet_read (data, len);
|
do_telnet_read (data, len);
|
||||||
return 1;
|
return 1;
|
||||||
@ -491,6 +489,11 @@ static int telnet_receive(Socket skt, int urgent, char *data, int len) {
|
|||||||
* Also places the canonical host name into `realhost'.
|
* Also places the canonical host name into `realhost'.
|
||||||
*/
|
*/
|
||||||
static char *telnet_init (char *host, int port, char **realhost) {
|
static char *telnet_init (char *host, int port, char **realhost) {
|
||||||
|
static struct plug_function_table fn_table = {
|
||||||
|
telnet_closing,
|
||||||
|
telnet_receive
|
||||||
|
}, *fn_table_ptr = &fn_table;
|
||||||
|
|
||||||
SockAddr addr;
|
SockAddr addr;
|
||||||
char *err;
|
char *err;
|
||||||
|
|
||||||
@ -507,7 +510,7 @@ static char *telnet_init (char *host, int port, char **realhost) {
|
|||||||
/*
|
/*
|
||||||
* Open socket.
|
* Open socket.
|
||||||
*/
|
*/
|
||||||
s = sk_new(addr, port, 0, 1, telnet_receive);
|
s = sk_new(addr, port, 0, 1, &fn_table_ptr);
|
||||||
if ( (err = sk_socket_error(s)) )
|
if ( (err = sk_socket_error(s)) )
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
113
winnet.c
113
winnet.c
@ -49,6 +49,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define DEFINE_PLUG_METHOD_MACROS
|
||||||
#include "putty.h"
|
#include "putty.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "tree234.h"
|
#include "tree234.h"
|
||||||
@ -56,9 +57,11 @@
|
|||||||
#define BUFFER_GRANULE 512
|
#define BUFFER_GRANULE 512
|
||||||
|
|
||||||
struct Socket_tag {
|
struct Socket_tag {
|
||||||
|
struct socket_function_table *fn;
|
||||||
|
/* the above variable absolutely *must* be the first in this structure */
|
||||||
char *error;
|
char *error;
|
||||||
SOCKET s;
|
SOCKET s;
|
||||||
sk_receiver_t receiver;
|
Plug plug;
|
||||||
void *private_ptr;
|
void *private_ptr;
|
||||||
struct buffer *head, *tail;
|
struct buffer *head, *tail;
|
||||||
int writable;
|
int writable;
|
||||||
@ -66,6 +69,16 @@ struct Socket_tag {
|
|||||||
int oobinline;
|
int oobinline;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
struct SockAddr_tag {
|
struct SockAddr_tag {
|
||||||
char *error;
|
char *error;
|
||||||
/* address family this belongs to, AF_INET for IPv4, AF_INET6 for IPv6. */
|
/* address family this belongs to, AF_INET for IPv4, AF_INET6 for IPv6. */
|
||||||
@ -90,7 +103,7 @@ struct buffer {
|
|||||||
static tree234 *sktree;
|
static tree234 *sktree;
|
||||||
|
|
||||||
static int cmpfortree(void *av, void *bv) {
|
static int cmpfortree(void *av, void *bv) {
|
||||||
Socket a = (Socket)av, b = (Socket)bv;
|
Actual_Socket a = (Actual_Socket)av, b = (Actual_Socket)bv;
|
||||||
unsigned long as = (unsigned long)a->s, bs = (unsigned long)b->s;
|
unsigned long as = (unsigned long)a->s, bs = (unsigned long)b->s;
|
||||||
if (as < bs) return -1;
|
if (as < bs) return -1;
|
||||||
if (as > bs) return +1;
|
if (as > bs) return +1;
|
||||||
@ -98,7 +111,7 @@ static int cmpfortree(void *av, void *bv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int cmpforsearch(void *av, void *bv) {
|
static int cmpforsearch(void *av, void *bv) {
|
||||||
Socket b = (Socket)bv;
|
Actual_Socket b = (Actual_Socket)bv;
|
||||||
unsigned long as = (unsigned long)av, bs = (unsigned long)b->s;
|
unsigned long as = (unsigned long)av, bs = (unsigned long)b->s;
|
||||||
if (as < bs) return -1;
|
if (as < bs) return -1;
|
||||||
if (as > bs) return +1;
|
if (as > bs) return +1;
|
||||||
@ -289,8 +302,37 @@ void sk_addr_free(SockAddr addr) {
|
|||||||
sfree(addr);
|
sfree(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Plug sk_tcp_plug (Socket sock, Plug p) {
|
||||||
|
Actual_Socket s = (Actual_Socket) sock;
|
||||||
|
Plug ret = s->plug;
|
||||||
|
if (p) s->plug = p;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sk_tcp_flush (Socket s) {
|
||||||
|
/*
|
||||||
|
* We send data to the socket as soon as we can anyway,
|
||||||
|
* so we don't need to do anything here. :-)
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void sk_tcp_close (Socket s);
|
||||||
|
void sk_tcp_write (Socket s, char *data, int len);
|
||||||
|
void sk_tcp_write_oob (Socket s, char *data, int len);
|
||||||
|
char *sk_tcp_socket_error(Socket s);
|
||||||
|
|
||||||
Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||||
sk_receiver_t receiver) {
|
Plug plug)
|
||||||
|
{
|
||||||
|
static struct socket_function_table fn_table = {
|
||||||
|
sk_tcp_plug,
|
||||||
|
sk_tcp_close,
|
||||||
|
sk_tcp_write,
|
||||||
|
sk_tcp_write_oob,
|
||||||
|
sk_tcp_flush,
|
||||||
|
sk_tcp_socket_error
|
||||||
|
};
|
||||||
|
|
||||||
SOCKET s;
|
SOCKET s;
|
||||||
#ifdef IPV6
|
#ifdef IPV6
|
||||||
SOCKADDR_IN6 a6;
|
SOCKADDR_IN6 a6;
|
||||||
@ -298,7 +340,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
|||||||
SOCKADDR_IN a;
|
SOCKADDR_IN a;
|
||||||
DWORD err;
|
DWORD err;
|
||||||
char *errstr;
|
char *errstr;
|
||||||
Socket ret;
|
Actual_Socket ret;
|
||||||
extern char *do_select(SOCKET skt, int startup);
|
extern char *do_select(SOCKET skt, int startup);
|
||||||
short localport;
|
short localport;
|
||||||
|
|
||||||
@ -306,8 +348,9 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
|||||||
* Create Socket structure.
|
* Create Socket structure.
|
||||||
*/
|
*/
|
||||||
ret = smalloc(sizeof(struct Socket_tag));
|
ret = smalloc(sizeof(struct Socket_tag));
|
||||||
|
ret->fn = &fn_table;
|
||||||
ret->error = NULL;
|
ret->error = NULL;
|
||||||
ret->receiver = receiver;
|
ret->plug = plug;
|
||||||
ret->head = ret->tail = NULL;
|
ret->head = ret->tail = NULL;
|
||||||
ret->writable = 1; /* to start with */
|
ret->writable = 1; /* to start with */
|
||||||
ret->sending_oob = 0;
|
ret->sending_oob = 0;
|
||||||
@ -321,7 +364,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
|||||||
if (s == INVALID_SOCKET) {
|
if (s == INVALID_SOCKET) {
|
||||||
err = WSAGetLastError();
|
err = WSAGetLastError();
|
||||||
ret->error = winsock_error_string(err);
|
ret->error = winsock_error_string(err);
|
||||||
return ret;
|
return (Socket) ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret->oobinline = oobinline;
|
ret->oobinline = oobinline;
|
||||||
@ -384,7 +427,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
|||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
ret->error = winsock_error_string(err);
|
ret->error = winsock_error_string(err);
|
||||||
return ret;
|
return (Socket) ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -413,7 +456,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
|||||||
{
|
{
|
||||||
err = WSAGetLastError();
|
err = WSAGetLastError();
|
||||||
ret->error = winsock_error_string(err);
|
ret->error = winsock_error_string(err);
|
||||||
return ret;
|
return (Socket) ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up a select mechanism. This could be an AsyncSelect on a
|
/* Set up a select mechanism. This could be an AsyncSelect on a
|
||||||
@ -421,16 +464,17 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
|||||||
errstr = do_select(s, 1);
|
errstr = do_select(s, 1);
|
||||||
if (errstr) {
|
if (errstr) {
|
||||||
ret->error = errstr;
|
ret->error = errstr;
|
||||||
return ret;
|
return (Socket) ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
add234(sktree, ret);
|
add234(sktree, ret);
|
||||||
|
|
||||||
return ret;
|
return (Socket) ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sk_close(Socket s) {
|
static void sk_tcp_close(Socket sock) {
|
||||||
extern char *do_select(SOCKET skt, int startup);
|
extern char *do_select(SOCKET skt, int startup);
|
||||||
|
Actual_Socket s = (Actual_Socket) sock;
|
||||||
|
|
||||||
del234(sktree, s);
|
del234(sktree, s);
|
||||||
do_select(s->s, 0);
|
do_select(s->s, 0);
|
||||||
@ -442,7 +486,7 @@ void sk_close(Socket s) {
|
|||||||
* The function which tries to send on a socket once it's deemed
|
* The function which tries to send on a socket once it's deemed
|
||||||
* writable.
|
* writable.
|
||||||
*/
|
*/
|
||||||
void try_send(Socket s) {
|
void try_send(Actual_Socket s) {
|
||||||
while (s->head) {
|
while (s->head) {
|
||||||
int nsent;
|
int nsent;
|
||||||
DWORD err;
|
DWORD err;
|
||||||
@ -497,7 +541,9 @@ void try_send(Socket s) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sk_write(Socket s, char *buf, int len) {
|
static void sk_tcp_write(Socket sock, char *buf, int len) {
|
||||||
|
Actual_Socket s = (Actual_Socket) sock;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the data to the buffer list on the socket.
|
* Add the data to the buffer list on the socket.
|
||||||
*/
|
*/
|
||||||
@ -532,7 +578,9 @@ void sk_write(Socket s, char *buf, int len) {
|
|||||||
try_send(s);
|
try_send(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sk_write_oob(Socket s, char *buf, int len) {
|
static void sk_tcp_write_oob(Socket sock, char *buf, int len) {
|
||||||
|
Actual_Socket s = (Actual_Socket) sock;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Replace the buffer list on the socket with the data.
|
* Replace the buffer list on the socket with the data.
|
||||||
*/
|
*/
|
||||||
@ -567,7 +615,7 @@ int select_result(WPARAM wParam, LPARAM lParam) {
|
|||||||
int ret, open;
|
int ret, open;
|
||||||
DWORD err;
|
DWORD err;
|
||||||
char buf[BUFFER_GRANULE];
|
char buf[BUFFER_GRANULE];
|
||||||
Socket s;
|
Actual_Socket s;
|
||||||
u_long atmark;
|
u_long atmark;
|
||||||
|
|
||||||
/* wParam is the socket itself */
|
/* wParam is the socket itself */
|
||||||
@ -578,9 +626,9 @@ int select_result(WPARAM wParam, LPARAM lParam) {
|
|||||||
if ((err = WSAGETSELECTERROR(lParam)) != 0) {
|
if ((err = WSAGETSELECTERROR(lParam)) != 0) {
|
||||||
/*
|
/*
|
||||||
* An error has occurred on this socket. Pass it to the
|
* An error has occurred on this socket. Pass it to the
|
||||||
* receiver function.
|
* plug.
|
||||||
*/
|
*/
|
||||||
return s->receiver(s, 3, winsock_error_string(err), err);
|
return plug_closing (s->plug, winsock_error_string(err), err, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
noise_ultralight(lParam);
|
noise_ultralight(lParam);
|
||||||
@ -615,9 +663,11 @@ int select_result(WPARAM wParam, LPARAM lParam) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return s->receiver(s, 3, winsock_error_string(err), err);
|
return plug_closing (s->plug, winsock_error_string(err), err, 0);
|
||||||
|
} else if (0 == ret) {
|
||||||
|
return plug_closing (s->plug, NULL, 0, 0);
|
||||||
} else {
|
} else {
|
||||||
return s->receiver(s, atmark ? 0 : 1, buf, ret);
|
return plug_receive (s->plug, atmark ? 0 : 1, buf, ret);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FD_OOB:
|
case FD_OOB:
|
||||||
@ -633,7 +683,7 @@ int select_result(WPARAM wParam, LPARAM lParam) {
|
|||||||
fatalbox(ret == 0 ? "Internal networking trouble" :
|
fatalbox(ret == 0 ? "Internal networking trouble" :
|
||||||
winsock_error_string(WSAGetLastError()));
|
winsock_error_string(WSAGetLastError()));
|
||||||
} else {
|
} else {
|
||||||
return s->receiver(s, 2, buf, ret);
|
return plug_receive (s->plug, 2, buf, ret);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FD_WRITE:
|
case FD_WRITE:
|
||||||
@ -649,9 +699,11 @@ int select_result(WPARAM wParam, LPARAM lParam) {
|
|||||||
err = WSAGetLastError();
|
err = WSAGetLastError();
|
||||||
if (err == WSAEWOULDBLOCK)
|
if (err == WSAEWOULDBLOCK)
|
||||||
break;
|
break;
|
||||||
return s->receiver(s, 3, winsock_error_string(err), err);
|
return plug_closing (s->plug, winsock_error_string(err), err, 0);
|
||||||
} else
|
} else {
|
||||||
open &= s->receiver(s, 0, buf, ret);
|
if (ret) open &= plug_receive (s->plug, 0, buf, ret);
|
||||||
|
else open &= plug_closing (s->plug, NULL, 0, 0);
|
||||||
|
}
|
||||||
} while (ret > 0);
|
} while (ret > 0);
|
||||||
return open;
|
return open;
|
||||||
}
|
}
|
||||||
@ -663,10 +715,12 @@ int select_result(WPARAM wParam, LPARAM lParam) {
|
|||||||
* Each socket abstraction contains a `void *' private field in
|
* Each socket abstraction contains a `void *' private field in
|
||||||
* which the client can keep state.
|
* which the client can keep state.
|
||||||
*/
|
*/
|
||||||
void sk_set_private_ptr(Socket s, void *ptr) {
|
void sk_set_private_ptr(Socket sock, void *ptr) {
|
||||||
|
Actual_Socket s = (Actual_Socket) sock;
|
||||||
s->private_ptr = ptr;
|
s->private_ptr = ptr;
|
||||||
}
|
}
|
||||||
void *sk_get_private_ptr(Socket s) {
|
void *sk_get_private_ptr(Socket sock) {
|
||||||
|
Actual_Socket s = (Actual_Socket) sock;
|
||||||
return s->private_ptr;
|
return s->private_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -678,7 +732,8 @@ void *sk_get_private_ptr(Socket s) {
|
|||||||
char *sk_addr_error(SockAddr addr) {
|
char *sk_addr_error(SockAddr addr) {
|
||||||
return addr->error;
|
return addr->error;
|
||||||
}
|
}
|
||||||
char *sk_socket_error(Socket s) {
|
static char *sk_tcp_socket_error(Socket sock) {
|
||||||
|
Actual_Socket s = (Actual_Socket) sock;
|
||||||
return s->error;
|
return s->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -686,10 +741,10 @@ char *sk_socket_error(Socket s) {
|
|||||||
* For Plink: enumerate all sockets currently active.
|
* For Plink: enumerate all sockets currently active.
|
||||||
*/
|
*/
|
||||||
SOCKET first_socket(enum234 *e) {
|
SOCKET first_socket(enum234 *e) {
|
||||||
Socket s = first234(sktree, e);
|
Actual_Socket s = first234(sktree, e);
|
||||||
return s ? s->s : INVALID_SOCKET;
|
return s ? s->s : INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
SOCKET next_socket(enum234 *e) {
|
SOCKET next_socket(enum234 *e) {
|
||||||
Socket s = next234(e);
|
Actual_Socket s = next234(e);
|
||||||
return s ? s->s : INVALID_SOCKET;
|
return s ? s->s : INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
50
x11fwd.c
50
x11fwd.c
@ -62,12 +62,15 @@ extern void sshfwd_close(void *);
|
|||||||
extern void sshfwd_write(void *, char *, int);
|
extern void sshfwd_write(void *, char *, int);
|
||||||
|
|
||||||
struct X11Private {
|
struct X11Private {
|
||||||
|
struct plug_function_table *fn;
|
||||||
|
/* the above variable absolutely *must* be the first in this structure */
|
||||||
unsigned char firstpkt[12]; /* first X data packet */
|
unsigned char firstpkt[12]; /* first X data packet */
|
||||||
char *auth_protocol;
|
char *auth_protocol;
|
||||||
unsigned char *auth_data;
|
unsigned char *auth_data;
|
||||||
int data_read, auth_plen, auth_psize, auth_dlen, auth_dsize;
|
int data_read, auth_plen, auth_psize, auth_dlen, auth_dsize;
|
||||||
int verified;
|
int verified;
|
||||||
void *c; /* data used by ssh.c */
|
void *c; /* data used by ssh.c */
|
||||||
|
Socket s;
|
||||||
};
|
};
|
||||||
|
|
||||||
void x11_close (Socket s);
|
void x11_close (Socket s);
|
||||||
@ -103,23 +106,22 @@ static int x11_verify(char *proto, unsigned char *data, int dlen) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int x11_receive (Socket s, int urgent, char *data, int len) {
|
static int x11_closing (Plug plug, char *error_msg, int error_code, int calling_back) {
|
||||||
struct X11Private *pr = (struct X11Private *)sk_get_private_ptr(s);
|
struct X11Private *pr = (struct X11Private *) plug;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have no way to communicate down the forwarded connection,
|
||||||
|
* so if an error occurred on the socket, we just ignore it
|
||||||
|
* and treat it like a proper close.
|
||||||
|
*/
|
||||||
|
sshfwd_close(pr->c);
|
||||||
|
x11_close(pr->s);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int x11_receive (Plug plug, int urgent, char *data, int len) {
|
||||||
|
struct X11Private *pr = (struct X11Private *) plug;
|
||||||
|
|
||||||
if (urgent==3) {
|
|
||||||
/*
|
|
||||||
* A socket error has occurred. We have no way to
|
|
||||||
* communicate this down the forwarded connection, so we'll
|
|
||||||
* just treat it like a proper close.
|
|
||||||
*/
|
|
||||||
len = 0;
|
|
||||||
}
|
|
||||||
if (!len) {
|
|
||||||
/* Connection has closed. */
|
|
||||||
sshfwd_close(pr->c);
|
|
||||||
x11_close(s);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
sshfwd_write(pr->c, data, len);
|
sshfwd_write(pr->c, data, len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -131,6 +133,11 @@ static int x11_receive (Socket s, int urgent, char *data, int len) {
|
|||||||
* also, fills the SocketsStructure
|
* also, fills the SocketsStructure
|
||||||
*/
|
*/
|
||||||
char *x11_init (Socket *s, char *display, void *c) {
|
char *x11_init (Socket *s, char *display, void *c) {
|
||||||
|
static struct plug_function_table fn_table = {
|
||||||
|
x11_closing,
|
||||||
|
x11_receive
|
||||||
|
};
|
||||||
|
|
||||||
SockAddr addr;
|
SockAddr addr;
|
||||||
int port;
|
int port;
|
||||||
char *err, *dummy_realhost;
|
char *err, *dummy_realhost;
|
||||||
@ -163,16 +170,19 @@ char *x11_init (Socket *s, char *display, void *c) {
|
|||||||
/*
|
/*
|
||||||
* Open socket.
|
* Open socket.
|
||||||
*/
|
*/
|
||||||
*s = sk_new(addr, port, 0, 1, x11_receive);
|
|
||||||
if ( (err = sk_socket_error(*s)) )
|
|
||||||
return err;
|
|
||||||
|
|
||||||
pr = (struct X11Private *)smalloc(sizeof(struct X11Private));
|
pr = (struct X11Private *)smalloc(sizeof(struct X11Private));
|
||||||
|
pr->fn = &fn_table;
|
||||||
pr->auth_protocol = NULL;
|
pr->auth_protocol = NULL;
|
||||||
pr->verified = 0;
|
pr->verified = 0;
|
||||||
pr->data_read = 0;
|
pr->data_read = 0;
|
||||||
pr->c = c;
|
pr->c = c;
|
||||||
|
|
||||||
|
pr->s = *s = sk_new(addr, port, 0, 1, (Plug) pr);
|
||||||
|
if ( (err = sk_socket_error(*s)) ) {
|
||||||
|
sfree (pr);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
sk_set_private_ptr(*s, pr);
|
sk_set_private_ptr(*s, pr);
|
||||||
sk_addr_free(addr);
|
sk_addr_free(addr);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user