Commit 6a89fbd2 authored by tonu@x3.internalnet's avatar tonu@x3.internalnet

Merge work.mysql.com:/home/bk/mysql-4.0

into x3.internalnet:/home/tonu/bk/mysql-4.0-modified
parents a3be64bf b8670d48
...@@ -7,7 +7,9 @@ monty@donna.mysql.fi ...@@ -7,7 +7,9 @@ monty@donna.mysql.fi
monty@work.mysql.com monty@work.mysql.com
mwagner@evoq.mwagner.org mwagner@evoq.mwagner.org
paul@central.snake.net paul@central.snake.net
root@x3.internalnet
sasha@mysql.sashanet.com sasha@mysql.sashanet.com
serg@serg.mysql.com serg@serg.mysql.com
tim@threads.polyesthetic.msg tim@threads.polyesthetic.msg
tim@work.mysql.com tim@work.mysql.com
tonu@x3.internalnet
...@@ -22,7 +22,7 @@ TAR = gtar ...@@ -22,7 +22,7 @@ TAR = gtar
EXTRA_DIST = INSTALL-SOURCE README \ EXTRA_DIST = INSTALL-SOURCE README \
COPYING COPYING.LIB MIRRORS COPYING COPYING.LIB MIRRORS
SUBDIRS = include @docs_dirs@ @readline_dir@ \ SUBDIRS = include @docs_dirs@ @readline_dir@ \
@thread_dirs@ @pstack_dirs@ @sql_client_dirs@ \ @thread_dirs@ @pstack_dirs@ vio @sql_client_dirs@ \
@sql_server_dirs@ @libmysqld_dirs@ scripts tests man \ @sql_server_dirs@ @libmysqld_dirs@ scripts tests man \
@bench_dirs@ support-files @fs_dirs@ @bench_dirs@ support-files @fs_dirs@
......
...@@ -163,9 +163,15 @@ ...@@ -163,9 +163,15 @@
/* new UNIXWARE7 threads that are not yet posix */ /* new UNIXWARE7 threads that are not yet posix */
#undef HAVE_UNIXWARE7_POSIX #undef HAVE_UNIXWARE7_POSIX
/* OpenSSL */
#undef HAVE_OPENSSL
/* READLINE: */ /* READLINE: */
#undef HAVE_USG_SIGHOLD #undef HAVE_USG_SIGHOLD
/* Virtual IO */
#undef HAVE_VIO
/* Handling of large files on Solaris 2.6 */ /* Handling of large files on Solaris 2.6 */
#undef _LARGEFILE_SOURCE #undef _LARGEFILE_SOURCE
......
...@@ -642,6 +642,57 @@ fi ...@@ -642,6 +642,57 @@ fi
AC_MSG_RESULT($ac_cv_conv_longlong_to_float) AC_MSG_RESULT($ac_cv_conv_longlong_to_float)
]) ])
AC_DEFUN(MYSQL_CHECK_VIO, [
AC_ARG_WITH([vio],
[\
--with-vio Include the Virtual IO support],
[vio="$withval"],
[vio=no])
if test "$vio" = "yes"
then
vio_dir="vio"
vio_libs="../vio/libvio.la"
AC_DEFINE(HAVE_VIO)
else
vio_dir=""
vio_libs=""
fi
AC_SUBST([vio_dir])
AC_SUBST([vio_libs])
])
AC_DEFUN(MYSQL_CHECK_OPENSSL, [
AC_MSG_CHECKING(for OpenSSL)
AC_ARG_WITH([openssl],
[\
--with-openssl Include the OpenSSL support],
[openssl="$withval"],
[openssl=no])
if test "$openssl" = "yes"
then
if test -n "$vio_dir"
then
AC_MSG_RESULT(yes)
openssl_libs="-lssl -lcrypto -L/usr/local/ssl/lib"
openssl_includes="-I/usr/local/ssl/include"
else
AC_MSG_ERROR([OpenSSL requires Virtual IO support (--with-vio)])
fi
AC_DEFINE(HAVE_OPENSSL)
else
AC_MSG_RESULT(no)
openssl_libs=""
openssl_includes=""
fi
NON_THREADED_CLIENT_LIBS="$NON_THREADED_CLIENT_LIBS $openssl_libs"
AC_SUBST([openssl_libs])
AC_SUBST([openssl_includes])
])
AC_DEFUN(MYSQL_CHECK_MYSQLFS, [ AC_DEFUN(MYSQL_CHECK_MYSQLFS, [
AC_ARG_WITH([mysqlfs], AC_ARG_WITH([mysqlfs],
[\ [\
......
...@@ -24,7 +24,7 @@ INCLUDES = @MT_INCLUDES@ \ ...@@ -24,7 +24,7 @@ INCLUDES = @MT_INCLUDES@ \
@bdb_includes@ @innodb_includes@ @gemini_includes@ \ @bdb_includes@ @innodb_includes@ @gemini_includes@ \
-I$(srcdir)/../include \ -I$(srcdir)/../include \
-I$(srcdir)/../regex \ -I$(srcdir)/../regex \
-I$(srcdir) -I../include -I.. -I. -I$(srcdir) -I../include -I.. -I. $(openssl_includes)
WRAPLIBS= @WRAPLIBS@ WRAPLIBS= @WRAPLIBS@
SUBDIRS = share SUBDIRS = share
bin_PROGRAMS = mysqlbinlog bin_PROGRAMS = mysqlbinlog
...@@ -39,11 +39,12 @@ LDADD = ../isam/libnisam.a \ ...@@ -39,11 +39,12 @@ LDADD = ../isam/libnisam.a \
../mysys/libmysys.a \ ../mysys/libmysys.a \
../dbug/libdbug.a \ ../dbug/libdbug.a \
../regex/libregex.a \ ../regex/libregex.a \
../vio/libvio.a \
../strings/libmystrings.a ../strings/libmystrings.a
mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \ mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \
@bdb_libs@ @innodb_libs@ @pstack_libs@ \ @bdb_libs@ @innodb_libs@ @pstack_libs@ \
@gemini_libs@ \ @gemini_libs@ \
$(LDADD) $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@ $(LDADD) $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@ @openssl_libs@
noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
item_strfunc.h item_timefunc.h item_uniq.h \ item_strfunc.h item_timefunc.h item_uniq.h \
item_create.h mysql_priv.h \ item_create.h mysql_priv.h \
...@@ -62,7 +63,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ ...@@ -62,7 +63,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \ item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \
thr_malloc.cc item_create.cc \ thr_malloc.cc item_create.cc \
field.cc key.cc sql_class.cc sql_list.cc \ field.cc key.cc sql_class.cc sql_list.cc \
net_serv.cc violite.c net_pkg.cc lock.cc my_lock.c \ net_serv.cc net_pkg.cc lock.cc my_lock.c \
sql_string.cc sql_manager.cc sql_map.cc \ sql_string.cc sql_manager.cc sql_map.cc \
mysqld.cc password.c hash_filo.cc hostname.cc \ mysqld.cc password.c hash_filo.cc hostname.cc \
convert.cc sql_parse.cc sql_yacc.yy \ convert.cc sql_parse.cc sql_yacc.yy \
...@@ -85,7 +86,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ ...@@ -85,7 +86,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
gen_lex_hash_SOURCES = gen_lex_hash.cc gen_lex_hash_SOURCES = gen_lex_hash.cc
gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS) gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS)
mysqlbinlog_SOURCES = mysqlbinlog.cc mini_client.cc net_serv.cc \ mysqlbinlog_SOURCES = mysqlbinlog.cc mini_client.cc net_serv.cc \
mini_client_errors.c violite.c password.c mini_client_errors.c password.c
mysqlbinlog_LDADD = $(LDADD) $(CXXLDFLAGS) $(mysqld_LDADD) mysqlbinlog_LDADD = $(LDADD) $(CXXLDFLAGS) $(mysqld_LDADD)
DEFS = -DMYSQL_SERVER \ DEFS = -DMYSQL_SERVER \
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <nisam.h> #include <nisam.h>
#include <thr_alarm.h> #include <thr_alarm.h>
#include <ft_global.h> #include <ft_global.h>
#include "vio.h"
#ifndef DBUG_OFF #ifndef DBUG_OFF
#define ONE_THREAD #define ONE_THREAD
...@@ -243,7 +244,7 @@ static char *opt_ssl_key = 0; ...@@ -243,7 +244,7 @@ static char *opt_ssl_key = 0;
static char *opt_ssl_cert = 0; static char *opt_ssl_cert = 0;
static char *opt_ssl_ca = 0; static char *opt_ssl_ca = 0;
static char *opt_ssl_capath = 0; static char *opt_ssl_capath = 0;
static VioSSLAcceptorFd* ssl_acceptor_fd = 0; static struct st_VioSSLAcceptorFd * ssl_acceptor_fd = 0;
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
...@@ -518,7 +519,7 @@ static void close_connections(void) ...@@ -518,7 +519,7 @@ static void close_connections(void)
/* Force remaining threads to die by closing the connection to the client */ /* Force remaining threads to die by closing the connection to the client */
(void) my_net_init(&net, (Vio*) 0); (void) my_net_init(&net, (st_vio*) 0);
for (;;) for (;;)
{ {
DBUG_PRINT("quit",("Locking LOCK_thread_count")); DBUG_PRINT("quit",("Locking LOCK_thread_count"));
...@@ -960,7 +961,7 @@ void yyerror(const char *s) ...@@ -960,7 +961,7 @@ void yyerror(const char *s)
void close_connection(NET *net,uint errcode,bool lock) void close_connection(NET *net,uint errcode,bool lock)
{ {
Vio* vio; st_vio* vio;
DBUG_ENTER("close_connection"); DBUG_ENTER("close_connection");
DBUG_PRINT("enter",("fd: %s error: '%s'", DBUG_PRINT("enter",("fd: %s error: '%s'",
net->vio? vio_description(net->vio):"(not connected)", net->vio? vio_description(net->vio):"(not connected)",
...@@ -1609,8 +1610,9 @@ int main(int argc, char **argv) ...@@ -1609,8 +1610,9 @@ int main(int argc, char **argv)
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
if (opt_use_ssl) if (opt_use_ssl)
{ {
ssl_acceptor_fd = VioSSLAcceptorFd_new(opt_ssl_key, opt_ssl_cert, ssl_acceptor_fd = new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert,
opt_ssl_ca, opt_ssl_capath); opt_ssl_ca, opt_ssl_capath);
DBUG_PRINT("info",("ssl_acceptor_fd: %p",ssl_acceptor_fd));
if (!ssl_acceptor_fd) if (!ssl_acceptor_fd)
opt_use_ssl=0; opt_use_ssl=0;
/* having ssl_acceptor_fd!=0 signals the use of SSL */ /* having ssl_acceptor_fd!=0 signals the use of SSL */
...@@ -2025,7 +2027,7 @@ static int bootstrap(FILE *file) ...@@ -2025,7 +2027,7 @@ static int bootstrap(FILE *file)
int error; int error;
thd->bootstrap=1; thd->bootstrap=1;
thd->client_capabilities=0; thd->client_capabilities=0;
my_net_init(&thd->net,(Vio*) 0); my_net_init(&thd->net,(st_vio*) 0);
thd->max_packet_length=thd->net.max_packet; thd->max_packet_length=thd->net.max_packet;
thd->master_access= ~0; thd->master_access= ~0;
thd->thread_id=thread_id++; thd->thread_id=thread_id++;
...@@ -2162,7 +2164,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused))) ...@@ -2162,7 +2164,7 @@ pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
THD *thd; THD *thd;
struct sockaddr_in cAddr; struct sockaddr_in cAddr;
int ip_flags=0,socket_flags=0,flags; int ip_flags=0,socket_flags=0,flags;
Vio *vio_tmp; st_vio *vio_tmp;
DBUG_ENTER("handle_connections_sockets"); DBUG_ENTER("handle_connections_sockets");
LINT_INIT(new_sock); LINT_INIT(new_sock);
......
/*
** Virtual I/O library
** Written by Andrei Errapart <andreie@no.spam.ee>
*/
#ifdef __GNUC__
#pragma implementation // gcc: Class implementation
#endif
#include "vio-global.h"
VIO_NS_BEGIN
void
Vio::release()
{
delete this;
}
Vio::~Vio()
{
}
VIO_NS_END
/*
* Abstract Virtual IO interface - class Vio. Heavily
* influenced by Berkeley sockets and oriented toward MySQL.
*/
/*
** Virtual I/O library
** Written by Andrei Errapart <andreie@no.spam.ee>
** Modified by Monty
*/
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
VIO_NS_BEGIN
enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET,
VIO_TYPE_NAMEDPIPE, VIO_TYPE_SSL};
class Vio {
public:
virtual bool is_open() const = 0;
virtual int read(vio_ptr buf, int size) = 0;
virtual int write(const vio_ptr buf, int size) = 0;
virtual int blocking(bool onoff) = 0;
virtual bool blocking() const = 0;
virtual bool fcntl() const = 0;
virtual int fastsend(bool onoff = true) = 0;
virtual int keepalive(bool onoff) = 0;
virtual bool should_retry() const = 0;
virtual int close() = 0;
virtual void release();
virtual const char* description() const = 0;
virtual bool peer_addr(char *buf) const = 0;
virtual const char* cipher_description() const = 0;
virtual int vio_errno();
virtual ~Vio();
};
/* Macros to simulate the violite C interface */
Vio *vio_new(my_socket sd, enum enum_vio_type type,
my_bool localhost);
#ifdef __WIN__
Vio* vio_new_win32pipe(HANDLE hPipe);
#endif
#define vio_delete(vio) delete vio
#define vio_read(vio,buf,size) vio->read(buf,size)
#define vio_write(vio,buf,size) vio->write(buf,size)
#define vio_blocking(vio,mode) vio->blocking(mode)
#define vio_is_blocking(vio) vio->is_blocking()
#define vio_fastsend(vio,mode) vio->fastsend(mode)
#define vio_keepalive(vio,mode) vio->keepalive(mode)
#define vio_shouldretry(vio) vio->shouldretry(mode)
#define vio_close(vio) vio->close()
#define vio_description(vio) vio->description()
#define vio_errno(Vio *vio) vio->errno()
#define vio_peer_addr(vio,buf) vio->peer_addr(buf)
#define vio_in_addr(vio,in) vio->in_addr(in)
VIO_NS_END
/*
** Virtual I/O library
** Written by Andrei Errapart <andreie@no.spam.ee>
*/
#include "vio-global.h"
#ifdef __GNUC__
#pragma implementation // gcc: Class implementation
#endif
VIO_NS_BEGIN
VioAcceptorFd::~VioAcceptorFd()
{
}
VIO_NS_END
/*
** Virtual I/O library
** Written by Andrei Errapart <andreie@no.spam.ee>
*/
/*
* Abstract acceptor.
*/
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
VIO_NS_BEGIN
class VioAcceptorFd
{
public:
virtual ~VioAcceptorFd();
virtual Vio* accept( int fd) = 0;
};
VIO_NS_END
/*
* Unneccessary virtual destructor.
*/
#include "vio-global.h"
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include "viotypes.h"
#include "Vio.h"
#include "VioConnectorFd.h"
VIO_NS_BEGIN
VioConnectorFd::~VioConnectorFd()
{
}
VIO_NS_END
/*
* Abstract connector. The file (or socket) descriptor has to be
* prepared.
*/
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
VIO_NS_BEGIN
class VioConnectorFd
{
public:
virtual ~VioConnectorFd();
virtual Vio* connect(int fd) = 0;
};
VIO_NS_END
/*
** Virtual I/O library for files
** Written by Andrei Errapart <andreie@no.spam.ee>
** Checked and modfied by Monty
*/
#include "vio-global.h"
#include <assert.h>
#ifdef __GNUC__
#pragma implementation // gcc: Class implementation
#endif
VIO_NS_BEGIN
VioFd::VioFd( int fd) : fd_(fd)
{
sprintf(desc_, "VioFd(%d)", fd_);
}
VioFd:: ~VioFd()
{
if (fd_ >= 0)
{
it r = ::close(fd_);
if ( r < 0)
{
/* FIXME: error handling (Not Critical for MySQL) */
}
}
}
bool
VioFd::open() const
{
return fd_ >= 0;
}
int
VioFd::read(vio_ptr buf, int size)
{
assert(fd_>=0);
return ::read(fd_, buf, size);
}
int
VioFd::write(const vio_ptr buf, int size)
{
assert(fd_>=0);
return ::write(fd_, buf, size);
}
int
VioFd::blocking(bool onoff)
{
if (onoff)
return 0;
else
return -1;
}
bool
VioFd::blocking() const
{
return true;
}
int
VioFd::fastsend(bool tmp)
{
return 0;
}
int
VioFd::keepalive(boolonoff)
{
return -2; // Why -2 ? (monty)
}
bool
VioFd::fcntl() const
{
return FALSE;
}
bool
VioFd::should_retry() const
{
return FALSE;
}
int
VioFd::fcntl(int cmd)
{
assert(fd_>=0);
return ::fcntl(fd_, cmd);
}
int
VioFd::fcntl(int cmd, long arg)
{
assert(fd_>=0);
return ::fcntl(fd_, cmd, arg);
}
int
VioFd::fcntl(int cmd, struct flock* lock)
{
assert(fd_>=0);
return ::fcntl(fd_, cmd, lock);
}
int
VioFd::close()
{
int r = -2;
if (fd_>=0)
{
if ((r= ::close(fd_)) == 0)
fd_ = -1;
}
else
{
/* FIXME: error handling */
}
return r;
}
const char*
VioFd::description() const
{
return desc_;
}
const char*
VioFd::peer_addr() const
{
return "";
}
const char*
VioFd::peer_name() const
{
return "localhost";
}
const char*
VioFd::cipher_description() const
{
return "";
}
VIO_NS_END
/*
* Concrete Vio around a file descriptor.
*/
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
VIO_NS_BEGIN
class VioFd : public Vio
{
public:
VioFd( int fd);
virtual ~VioFd();
virtual bool open() const;
virtual int read( vio_ptr buf, int size);
virtual int write( const vio_ptr buf, int size);
virtual bool blocking() const;
virtual int blocking(bool onoff);
virtual int fastsend(bool onoff=true);
virtual int keepalive( bool onoff);
virtual bool fcntl() const;
virtual bool should_retry() const;
virtual int fcntl( int cmd);
virtual int fcntl( int cmd, long arg);
virtual int fcntl( int cmd, struct flock* lock);
virtual int close();
virtual const char* description() const;
virtual const char* peer_addr() const;
virtual bool peer_name(char *buf) const;
virtual const char* cipher_description() const;
private:
int fd_;
char desc_[100];
};
VIO_NS_END
/*
** Virtual I/O library for Windows named pipes
** Written by Monty
*/
#ifdef __WIN32__
#include "vio-global.h"
#ifdef __GNUC__
#pragma implementation // gcc: Class implementation
#endif
VIO_NS_BEGIN
VIO_NS_END
#endif /* WIN32 */
/*
* Concrete Vio around Handle.
*/
#ifdef __WIN__
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
VIO_NS_BEGIN
class VioPipe : public Vio
{
public:
VioPipe(int fd);
virtual ~VioPipe();
virtual bool is_open() const;
virtual int read(vio_ptr buf, int size);
virtual int write(const vio_ptr buf, int size);
virtual int blocking(bool onoff);
virtual bool blocking() const;
virtual bool fcntl() const;
virtual int fastsend(bool onoff = true);
virtual int keepalive(bool onoff);
virtual bool should_retry() const;
virtual int close();
virtual void release();
virtual const char* description() const;
virtual bool peer_addr(char *buf) const;
virtual const char* cipher_description() const { return "";}
virtual int vio_errno();
private:
};
VIO_NS_END
#endif /* WIN32 */
/*
** Virtual I/O library for SSL wrapper
** Written by Andrei Errapart <andreie@no.spam.ee>
*/
/*
* This file has some huge DBUG_ statements. Boy, this is silly...
*/
#include "vio-global.h"
#ifdef VIO_HAVE_OPENSSL
#include <assert.h>
#include <netinet/in.h>
#include <openssl/x509.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#ifdef __GNUC__
#pragma implementation // gcc: Class implementation
#endif
VIO_NS_BEGIN
#define this_ssl_con my_static_cast(SSL*)(this->ssl_con_)
#define this_bio my_static_cast(BIO*)(this->bio_)
typedef char* dataptr_t;
static void
report_errors()
{
unsigned long l;
const char* file;
const char* data;
int line,flags;
DBUG_ENTER("VioSSLConnectorFd::report_errors");
while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
{
char buf[200];
DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
file,line,(flags&ERR_TXT_STRING)?data:"")) ;
}
DBUG_VOID_RETURN;
}
//FIXME: duplicate code!
VioSSL::VioSSL(int fd,
vio_ptr ssl_context,
int state)
: bio_(0), ssl_con_(0), open_(FALSE), sd_(new VioSocket(fd))
{
DBUG_ENTER("VioSSL::VioSSL");
DBUG_PRINT("enter", ("this=%p, fd=%d, ssl_context=%p, state=%d",
this, fd, ssl_context, state));
assert(fd!=0);
assert(ssl_context!=0);
assert(state==state_connect || state==state_accept);
if (!init_bio_(fd, ssl_context, state, BIO_NOCLOSE))
open_ = true;
DBUG_VOID_RETURN;
}
VioSSL::VioSSL(VioSocket* sd,
vio_ptr ssl_context,
int state)
:bio_(0), ssl_con_(0), open_(FALSE), sd_(sd)
{
DBUG_ENTER("VioSSL::VioSSL");
DBUG_PRINT("enter",
("this=%p, sd=%s, ssl_context=%p, state=%d",
this, sd ? sd->description() : "0", ssl_context, state));
assert(sd != 0);
assert(ssl_context != 0);
assert(state == state_connect || state==state_accept);
if (!init_bio_(sd->sd_, ssl_context, state, BIO_NOCLOSE))
open_ = true;
DBUG_VOID_RETURN;
}
VioSSL::~VioSSL()
{
DBUG_ENTER("VioSSL::~VioSSL");
DBUG_PRINT("enter", ("this=%p", this));
if (ssl_con_!=0)
{
SSL_shutdown(this_ssl_con);
SSL_free(this_ssl_con);
}
if (sd_!=0)
delete sd_;
/* FIXME: no need to close bio? */
/*
if (bio_!=0)
BIO_free(this_bio);
*/
DBUG_VOID_RETURN;
}
bool
VioSSL::is_open() const
{
return open_;
}
int
VioSSL::read(vio_ptr buf, int size)
{
int r;
DBUG_ENTER("VioSSL::read");
DBUG_PRINT("enter", ("this=%p, buf=%p, size=%d", this, buf, size));
assert(this_ssl_con != 0);
r = SSL_read(this_ssl_con, my_static_cast(dataptr_t)(buf), size);
if ( r< 0)
report_errors();
DBUG_PRINT("exit", ("r=%d", r));
DBUG_RETURN(r);
}
int
VioSSL::write(const vio_ptr buf, int size)
{
int r;
DBUG_ENTER("VioSSL::write");
DBUG_PRINT("enter", ("this=%p, buf=%p, size=%d", this, buf, size));
assert(this_ssl_con!=0);
r = SSL_write(this_ssl_con, my_static_cast(dataptr_t)(buf), size);
if (r<0)
report_errors();
DBUG_PRINT("exit", ("r=%d", r));
DBUG_RETURN(r);
}
int
VioSSL::blocking(bool onoff)
{
int r;
DBUG_ENTER("VioSSL::blocking");
DBUG_PRINT("enter", ("this=%p, onoff=%s", this, onoff?"true":"false"));
r = sd_->blocking(onoff);
DBUG_PRINT("exit", ("r=%d", (int)r ));
DBUG_RETURN(r);
}
bool
VioSSL::blocking() const
{
bool r;
DBUG_ENTER("VioSSL::blocking");
DBUG_PRINT("enter", ("this=%p", this));
r = sd_->blocking();
DBUG_PRINT("exit", ("r=%d", (int)r ));
DBUG_RETURN(r);
}
int
VioSSL::fastsend(bool onoff)
{
int r;
DBUG_ENTER("VioSSL::fastsend");
DBUG_PRINT("enter", ("this=%p, onoff=%d", this, (int) onoff));
r = sd_->fastsend(onoff);
DBUG_PRINT("exit", ("r=%d", (int)r ));
DBUG_RETURN(r);
}
int VioSSL::keepalive(bool onoff)
{
int r;
DBUG_ENTER("VioSSL::keepalive");
DBUG_PRINT("enter", ("this=%p, onoff=%d", this, (int) onoff));
r = sd_->keepalive(onoff);
DBUG_PRINT("exit", ("r=%d", int(r) ));
DBUG_RETURN(r);
}
bool
VioSSL::fcntl() const
{
bool r;
DBUG_ENTER("VioSSL::fcntl");
DBUG_PRINT("enter", ("this=%p", this));
r = sd_->fcntl();
DBUG_PRINT("exit", ("r=%d", (int)r ));
DBUG_RETURN(r);
}
bool
VioSSL::should_retry() const
{
bool r;
DBUG_ENTER("VioSSL::should_retry");
DBUG_PRINT("enter", ("this=%p", this));
r = sd_->should_retry();
DBUG_PRINT("exit", ("r=%d", (int)r ));
DBUG_RETURN(r);
}
int
VioSSL::close()
{
int r= -2;
DBUG_ENTER("VioSSL::close");
DBUG_PRINT("enter", ("this=%p", this));
if (ssl_con)
{
r = SSL_shutdown(this_ssl_con);
SSL_free(this_ssl_con);
ssl_con_ = 0;
BIO_free(this_bio);
bio_ = 0;
}
DBUG_PRINT("exit", ("r=%d", r));
DBUG_RETURN(r);
}
const char*
VioSSL::description() const
{
return desc_;
}
const char*
VioSSL::peer_addr() const
{
if (sd_!=0)
return sd != 0 ? sd_->peer_addr() : "";
}
const char*
VioSSL::peer_name() const
{
return sd != 0 ? sd_->peer_name() : "";
}
const char*
VioSSL::cipher_description() const
{
return SSL_get_cipher_name(this_ssl_con);
}
int
VioSSL::init_bio_(int fd,
vio_ptr ssl_context,
int state,
int bio_flags)
{
DBUG_ENTER("VioSSL::init_bio_");
DBUG_PRINT("enter",
("this=%p, fd=%p, ssl_context=%p, state=%d, bio_flags=%d",
this, fd, ssl_context, state, bio_flags));
if (!(ssl_con_ = SSL_new(my_static_cast(SSL_CTX*)(ssl_context))))
{
DBUG_PRINT("error", ("SSL_new failure"));
report_errors();
DBUG_RETURN(-1);
}
if (!(bio_ = BIO_new_socket(fd, bio_flags)))
{
DBUG_PRINT("error", ("BIO_new_socket failure"));
report_errors();
SSL_free(ssl_con_);
ssl_con_ =0;
DBUG_RETURN(-1);
}
SSL_set_bio(this_ssl_con, this_bio, this_bio);
switch(state) {
case state_connect:
SSL_set_connect_state(this_ssl_con);
break;
case state_accept:
SSL_set_accept_state(this_ssl_con);
break;
default:
assert(0);
}
sprintf(desc_, "VioSSL(%d)", fd);
ssl_cip_ = new SSL_CIPHER ;
DBUG_RETURN(0);
}
VIO_NS_END
#endif /* VIO_HAVE_OPENSSL */
/*
* Concrete Vio around OpenSSL's SSL structure.
*/
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
VIO_NS_BEGIN
class VioSocket;
class VioSSL : public Vio
{
public:
enum {
state_connect = 1,
state_accept = 2
};
public:
VioSSL(int fd, vio_ptr ssl_context, int state);
VioSSL(VioSocket* sd, vio_ptr ssl_context, int state);
virtual ~VioSSL();
virtual bool open() const;
virtual int read( vio_ptr buf, int size);
virtual int write( const vio_ptr buf, int size);
virtual bool blocking() const;
virtual int blocking(bool onoff);
virtual int fastsend(bool onoff=true);
virtual int keepalive(bool onoff);
virtual bool fcntl() const;
virtual bool should_retry() const;
virtual int close();
virtual const char* description() const;
virtual const char* peer_addr() const;
virtual const char* peer_name() const;
virtual const char* cipher_description() const;
private:
int init_bio_(int fd,
vio_ptr ssl_context,
int state,
int bio_flags);
vio_ptr bio_;
vio_ptr ssl_con_;
vio_ptr ssl_cip_;
char desc_[100];
bool open_;
VioSocket* sd_;
};
VIO_NS_END
#endif /* VIO_HAVE_OPENSSL */
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
/*
* Wrapper around SSL_CTX.
*/
#ifdef VIO_HAVE_OPENSSL
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
VIO_NS_BEGIN
class VioSSLAcceptorFd : public VioAcceptorFd
{
public:
VioSSLAcceptorFd(const char* key_file,
const char* cert_file,
const char* ca_file,
const char* ca_path);
virtual ~VioSSLAcceptorFd();
virtual VioSSL* accept(int fd);
virtual VioSSL* accept(VioSocket* sd);
private:
VioSSLAcceptorFd(const VioSSLAcceptorFd& rhs);//undefined
VioSSLAcceptorFd& operator=(const VioSSLAcceptorFd& rhs);//undefined
private:
void report_errors();
vio_ptr ssl_;
vio_ptr ssl_context_;
vio_ptr ssl_method_;
vio_ptr session_id_context_;
};
VIO_NS_END
/*
* The Factory where Vio's are made!
*/
class VioSSLConnectorFd : public VioConnectorFd
{
public:
VioSSLConnectorFd(const char* key_file,
const char* cert_file,
const char* ca_file,
const char* ca_path);
virtual ~VioSSLConnectorFd();
virtual VioSSL* connect(int fd);
virtual VioSSL* connect(VioSocket* sd);
private:
VioSSLConnectorFd(const VioSSLConnectorFd& rhs);//undefined
VioSSLConnectorFd& operator=(const VioSSLConnectorFd& rhs);//undefined
private:
void report_errors();
vio_ptr ssl_context_;
vio_ptr ssl_method_;
vio_ptr ssl_;
};
VIO_NS_END
#endif /* VIO_HAVE_OPENSSL */
/* Copyright Abandoned 2000 Monty Program KB
This file is public domain and comes with NO WARRANTY of any kind */
/*
** Virtual I/O library
** Written by Andrei Errapart <andreie@no.spam.ee>
*/
#include "vio-global.h"
#ifdef __GNUC__
#pragma implementation // gcc: Class implementation
#endif
#include <assert.h>
/*
* Probably no need to clean this up
*/
#ifdef _WIN32
#include <winsock.h>
#endif
#include <sys/types.h>
#if !defined(__WIN32__) && !defined(MSDOS)
#include <sys/socket.h>
#endif
#if !defined(MSDOS) && !defined(__WIN32__) && !defined(HAVE_BROKEN_NETINET_INCLUDES)
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#if !defined(alpha_linux_port)
#include <netinet/tcp.h>
#endif
#if defined(__EMX__)
#include <sys/ioctl.h>
#define ioctlsocket(A,B,C) ioctl((A),(B),(void *)(C),sizeof(*(C)))
#undef HAVE_FCNTL
#endif
#endif
#if defined(MSDOS) || defined(__WIN32__)
#ifdef __WIN32__
#undef errno
#undef EINTR
#undef EAGAIN
#define errno WSAGetLastError()
#define EINTR WSAEINTR
#define EAGAIN WSAEINPROGRESS
#endif
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
#endif
#ifdef __cplusplus
extern "C" { // Because of SCO 3.2V4.2
#endif
#ifndef __WIN32__
#include <sys/resource.h>
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
#include <netdb.h>
#include <sys/utsname.h>
#endif // __WIN32__
#ifdef __cplusplus
}
#endif
VIO_NS_BEGIN
#define this_ssl_cip my_static_cast(SSL_CIPHER*)(this->ssl_cip_)
VioSocket::VioSocket(vio_socket sd, enum_vio_type type, bool localhost)
:sd_(sd), localhost_(localhost), fcntl_(0),
fcntl_set_(FALSE), cipher_description_(0)
{
DBUG_ENTER("VioSocket::VioSocket");
DBUG_PRINT("enter", ("sd=%d", sd));
if (type == VIO_TYPE_SOCKET)
sprintf(desc_,"Socket (%d)",sd_);
else
sprintf(desc_,"TCP/IP (%d)",sd_);
DBUG_VOID_RETURN;
}
VioSocket::~VioSocket()
{
DBUG_ENTER("VioSocket::~VioSocket");
DBUG_PRINT("enter", ("sd_=%d", sd_));
if (sd_>=0)
close();
DBUG_VOID_RETURN;
}
bool
VioSocket::is_open() const
{
return sd_>=0;
}
int
VioSocket::read(vio_ptr buf, int size)
{
int r;
DBUG_ENTER("VioSocket::read");
DBUG_PRINT("enter", ("sd_=%d, buf=%p, size=%d", sd_, buf, size));
assert(sd_>=0);
#if defined(MSDOS) || defined(__WIN32__)
r = ::recv(sd_, buf, size,0);
#else
r = ::read(sd_, buf, size);
#endif
#ifndef DBUG_OFF
if ( r < 0)
{
DBUG_PRINT("error", ("Got error %d during read",errno));
}
#endif /* DBUG_OFF */
DBUG_PRINT("exit", ("%d", r));
DBUG_RETURN(r);
}
int
VioSocket::write(vio_ptr buf, int size)
{
int r;
DBUG_ENTER("VioSocket::write");
DBUG_PRINT("enter", ("sd_=%d, buf=%p, size=%d", sd_, buf, size));
assert(sd_>=0);
#if defined(__WIN32__)
r = ::send(sd_, buf, size,0);
#else
r = ::write(sd_, buf, size);
#endif /* __WIN32__ */
#ifndef DBUG_OFF
if (r < 0)
{
DBUG_PRINT("error", ("Got error %d on write",errno));
}
#endif /* DBUG_OFF */
DBUG_RETURN(r);
}
int
VioSocket::blocking(bool set_blocking_mode)
{
int r= 0;
DBUG_ENTER("VioSocket::blocking");
DBUG_PRINT("enter", ("set_blocking_mode: %d", (int) set_blocking_mode));
#if !defined(___WIN32__) && !defined(__EMX__)
#if !defined(NO_FCNTL_NONBLOCK)
assert(sd_>=0);
int old_fcntl=fcntl_;
if (!fcntl_set_)
{
fcntl_set_ = true;
old_fcntl= fcntl_ = fcntl(F_GETFL);
}
if (set_blocking_mode)
fcntl_&=~O_NONBLOCK; //clear bit
else
fcntl_|=O_NONBLOCK; //set bit
if (old_fcntl != fcntl_)
r = ::fcntl(sd_, F_SETFL, fcntl_);
#endif /* !defined(NO_FCNTL_NONBLOCK) */
#else /* !defined(__WIN32__) && !defined(__EMX__) */
{
ulong arg;
int old_fcntl=vio->fcntl_mode;
if (!vio->fcntl_set)
{
vio->fcntl_set = TRUE;
old_fnctl=vio->fcntl_mode=0;
}
if (set_blocking_mode)
{
arg = 0;
fcntl_&=~ O_NONBLOCK; //clear bit
}
else
{
arg = 1;
fcntl_|= O_NONBLOCK; //set bit
}
if (old_fcntl != fcntl_)
r = ioctlsocket(sd_,FIONBIO,(void*)&arg,sizeof(arg));
}
#endif
DBUG_RETURN(r);
}
bool
VioSocket::blocking() const
{
DBUG_ENTER("VioSocket::blocking");
bool r = !(fcntl_ & O_NONBLOCK);
DBUG_PRINT("exit", ("%d", (int)r));
DBUG_RETURN(r);
}
int
VioSocket::fastsend(bool onoff)
{
int r=0;
DBUG_ENTER("VioSocket::fastsend");
DBUG_PRINT("enter", ("onoff:%d", (int)onoff));
assert(sd_>=0);
#ifdef IPTOS_THROUGHPUT
#ifndef __EMX__
int tos = IPTOS_THROUGHPUT;
if (!setsockopt(sd_, IPPROTO_IP, IP_TOS, (void*) &tos, sizeof(tos)))
#endif /* !__EMX__ */
{
int nodelay = 1;
if (setsockopt(sd_, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay,
sizeof(nodelay)))
{
DBUG_PRINT("warning",
("Couldn't set socket option for fast send"));
r= -1;
}
}
#endif /* IPTOS_THROUGHPUT */
DBUG_PRINT("exit", ("%d", r));
DBUG_RETURN(0);
}
int
VioSocket::keepalive(bool set_keep_alive)
{
DBUG_ENTER("VioSocket::keepalive");
DBUG_PRINT("enter", ("sd_=%d, set_keep_alive=%d", sd_,
(int) set_keep_alive));
assert(sd_>=0);
uint opt= set_keep_alive ? 1 : 0;
DBUG_RETURN(setsockopt(sd_, SOL_SOCKET, SO_KEEPALIVE, (char*) &opt,
sizeof(opt)));
}
bool
VioSocket::should_retry() const
{
int en = errno;
return en == EAGAIN || en == EINTR || en == EWOULDBLOCK;
}
int
VioSocket::close()
{
DBUG_ENTER("VioSocket::close");
assert(sd_>=0);
int r=0;
if (::shutdown(sd_,2))
r= -1;
if (::closesocket(sd_))
r= -1;
if (r)
{
DBUG_PRINT("error", ("close() failed, error: %d",errno));
/* FIXME: error handling (not critical for MySQL) */
}
sd_ = -1;
DBUG_RETURN(r);
}
int
VioSocket::shutdown(int how)
{
DBUG_ENTER("VioSocket::shutdown");
DBUG_PRINT("enter", ("how=%d", how));
assert(sd_>=0);
int r = ::shutdown(sd_, how);
DBUG_PRINT("exit", ("%d", r));
DBUG_RETURN(r);
}
const char*
VioSocket::description() const
{
return desc_;
}
bool
VioSocket::peer_addr(char *buf) const
{
DBUG_ENTER("VioSocket::peer_addr");
DBUG_PRINT("enter", ("sd_=%d", sd_));
if (localhost_)
{
strmov(buf,"127.0.0.1");
}
else
{
size_socket addrLen= sizeof(struct sockaddr);
if (getpeername(sd_, my_reinterpret_cast(struct sockaddr *) (&remote_),
&addrLen) != 0)
{
DBUG_PRINT("exit", ("getpeername, error: %d", errno));
DBUG_RETURN(1);
}
my_inet_ntoa(remote_.sin_addr,buf);
}
DBUG_PRINT("exit", ("addr=%s", buf));
DBUG_RETURN(0);
}
const char*
VioSocket::cipher_description() const
{
DBUG_ENTER("VioSocket::cipher_description");
char *r = cipher_description_ ? cipher_description_:"";
DBUG_PRINT("exit", ("name: %s", r));
DBUG_RETURN(r);
}
VIO_NS_END
/*
** Virtual I/O library
** Written by Andrei Errapart <andreie@no.spam.ee>
*/
/*
* Concrete Vio around socket. Doesn't differ much from VioFd.
*/
#ifdef WIN32
typedef SOCKET vio_socket;
#else
typedef int vio_socket;
#endif /* WIN32 */
VIO_NS_BEGIN
class VioSSL;
class VioSocket : public Vio
{
public:
VioSocket(vio_socket sd, bool localhost=true);
virtual ~VioSocket();
virtual bool is_open() const;
virtual int read(vio_ptr buf, int size);
virtual int write(const vio_ptr buf, int size);
virtual int blocking(bool onoff);
virtual bool blocking() const;
virtual int fastsend(bool onoff=true);
virtual int keepalive(bool onoff);
virtual bool should_retry() const;
virtual int close();
virtual const char* description() const;
virtual bool peer_addr(char *buf) const;
virtual const char* cipher_description() const;
virtual int vio_errno();
int shutdown(int how);
private:
vio_socket sd_;
const bool localhost_;
int fcntl_;
bool fcntl_set_;
char desc_[30];
mutable struct sockaddr_in local_;
mutable struct sockaddr_in remote_;
mutable char* cipher_description_;
friend class VioSSL; // he wants to tinker with this->sd_;
};
VIO_NS_END
#endif /* vio_VioSocket_h_ */
#include "vio-global.h"
extern "C" const char*
vio_version()
{
return "0.2";
}
#include <global.h>
#if !defined(VIO_HAVE_OPENSSL) && defined(HAVE_OPENSSL)
#define VIO_HAVE_OPENSSL HAVE_OPENSSL
#endif /* !defined(VIO_HAVE_OPENSSL) && defined(HAVE_OPENSSL) */
#include "viotypes.h"
#include "Vio.h"
#include "VioAcceptorFd.h"
#include "VioFd.h"
#include "VioPipe.h"
#include "VioSocket.h"
#ifdef VIO_HAVE_OPENSSL
#include "VioSSL.h"
#include "VioSSLFactoriesFd.h"
#endif /* VIO_HAVE_OPENSSL */
#if VIO_HAVE_NAMESPACES
#define VIO_STD_NS std
#define VIO_STD_NS_USING using namespace std;
#define VIO_NS VirtualIO
#define VIO_NS_BEGIN namespace VIO_NS {
#define VIO_NS_END }
#define VIO_NS_USING using namespace VIO_NS;
#else
#define VIO_STD_NS
#define VIO_STD_NS_USING
#define VIO_NS
#define VIO_NS_BEGIN
#define VIO_NS_END
#define VIO_NS_USING
#endif
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Note that we can't have assertion on file descriptors; The reason for
this is that during mysql shutdown, another thread can close a file
we are working on. In this case we should just return read errors from
the file descriptior.
*/
#define DONT_MAP_VIO
#include <global.h>
#include <errno.h>
#include <assert.h>
#include <vio.h>
#include <my_sys.h>
#include <my_net.h>
#include <m_string.h>
#ifdef HAVE_POLL
#include <sys/poll.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#if defined(__EMX__)
#define ioctlsocket ioctl
#endif /* defined(__EMX__) */
#if defined(MSDOS) || defined(__WIN__)
#ifdef __WIN__
#undef errno
#undef EINTR
#undef EAGAIN
#define errno WSAGetLastError()
#define EINTR WSAEINTR
#define EAGAIN WSAEINPROGRESS
#endif /* __WIN__ */
#define O_NONBLOCK 1 /* For emulation of fcntl() */
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
#endif
/*
* Helper to fill most of the st_vio* with defaults.
*/
void vio_reset(st_vio* vio, enum enum_vio_type type,
my_socket sd, HANDLE hPipe,
my_bool localhost)
{
bzero((char*) vio, sizeof(st_vio));
vio->type = type;
vio->sd = sd;
vio->hPipe = hPipe;
vio->localhost= localhost;
#ifdef HAVE_VIO
if(type == VIO_TYPE_SSL){
vio->viodelete =vio_ssl_delete;
vio->vioerrno =vio_ssl_errno;
vio->read =vio_ssl_read;
vio->write =vio_ssl_write;
vio->fastsend =vio_ssl_fastsend;
vio->viokeepalive=vio_ssl_keepalive;
vio->should_retry=vio_ssl_should_retry;
vio->vioclose =vio_ssl_close;
vio->peer_addr =vio_ssl_peer_addr;
vio->in_addr =vio_ssl_in_addr;
vio->poll_read =vio_ssl_poll_read;
} else { /* default is VIO_TYPE_TCPIP */
vio->viodelete =vio_delete;
vio->vioerrno =vio_errno;
vio->read =vio_read;
vio->write =vio_write;
vio->fastsend =vio_fastsend;
vio->viokeepalive=vio_keepalive;
vio->should_retry=vio_should_retry;
vio->vioclose =vio_close;
vio->peer_addr =vio_peer_addr;
vio->in_addr =vio_in_addr;
vio->poll_read =vio_poll_read;
}
#endif /* HAVE_VIO */
}
/* Open the socket or TCP/IP connection and read the fnctl() status */
st_vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
{
st_vio *vio;
DBUG_ENTER("vio_new");
DBUG_PRINT("enter", ("sd=%d", sd));
if ((vio = (st_vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
{
vio_reset(vio, type, sd, 0, localhost);
sprintf(vio->desc,
(vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"),
vio->sd);
#if !defined(___WIN__) && !defined(__EMX__)
#if !defined(NO_FCNTL_NONBLOCK)
vio->fcntl_mode = fcntl(sd, F_GETFL);
#elif defined(HAVE_SYS_IOCTL_H) /* hpux */
/* Non blocking sockets doesn't work good on HPUX 11.0 */
(void) ioctl(sd,FIOSNBIO,0);
#endif
#else /* !defined(__WIN__) && !defined(__EMX__) */
{
/* set to blocking mode by default */
ulong arg=0, r;
r = ioctlsocket(sd,FIONBIO,(void*) &arg, sizeof(arg));
}
#endif
}
DBUG_RETURN(vio);
}
#ifdef __WIN__
st_vio *vio_new_win32pipe(HANDLE hPipe)
{
st_vio *vio;
DBUG_ENTER("vio_new_handle");
if ((vio = (st_vio*) my_malloc(sizeof(st_vio),MYF(MY_WME))))
{
vio_reset(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, TRUE);
strmov(vio->desc, "named pipe");
}
DBUG_RETURN(vio);
}
#endif
/* Copyright Abandoned 2000 Monty Program KB
This file is public domain and comes with NO WARRANTY of any kind */
/*
* Renamed of violite.cc to violitexx.cc because of clashes
* with violite.c
* This file implements the same functions as in violite.c, but now using
* the Vio class
*/
#include "vio-global.h"
Vio*
vio_new(my_socket sd, enum_vio_type type, my_bool localhost)
{
return my_reinterpret_cast(Vio*) (new VioSocket(sd, type, localhost));
}
#ifdef __WIN32__
Vio
*vio_new_win32pipe(HANDLE hPipe)
{
return my_reinterpret_cast(Vio*) (new VioPipe(hPipe));
}
#endif
/* Copyright Abandoned 2000 Monty Program KB
This file is public domain and comes with NO WARRANTY of any kind */
/*
* Vio Lite.
* Purpose: include file for Vio that will work with C and C++
*/
#ifndef vio_violite_h_
#define vio_violite_h_
#include "my_net.h" /* needed because of struct in_addr */
#ifdef HAVE_VIO
#include <Vio.h> /* Full VIO interface */
#else
/* Simple vio interface in C; The functions are implemented in violite.c */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef Vio_defined
#define Vio_defined
struct st_vio; /* Only C */
typedef struct st_vio Vio;
#endif
enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET,
VIO_TYPE_NAMEDPIPE, VIO_TYPE_SSL};
Vio* vio_new(my_socket sd,
enum enum_vio_type type,
my_bool localhost);
#ifdef __WIN__
Vio* vio_new_win32pipe(HANDLE hPipe);
#endif
void vio_delete(Vio* vio);
/*
* vio_read and vio_write should have the same semantics
* as read(2) and write(2).
*/
int vio_read( Vio* vio,
gptr buf, int size);
int vio_write( Vio* vio,
const gptr buf,
int size);
/*
* Whenever the socket is set to blocking mode or not.
*/
int vio_blocking( Vio* vio,
my_bool onoff);
my_bool vio_is_blocking( Vio* vio);
/*
* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible.
*/
int vio_fastsend( Vio* vio,
my_bool onoff);
/*
* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible.
*/
int vio_keepalive( Vio* vio,
my_bool onoff);
/*
* Whenever we should retry the last read/write operation.
*/
my_bool vio_should_retry( Vio* vio);
/*
* When the workday is over...
*/
int vio_close( Vio* vio);
/*
* Short text description of the socket for those, who are curious..
*/
const char* vio_description( Vio* vio);
/* Return the type of the connection */
enum enum_vio_type vio_type(Vio* vio);
/* Return last error number */
int vio_errno(Vio *vio);
/* Get socket number */
my_socket vio_fd(Vio *vio);
/*
* Remote peer's address and name in text form.
*/
my_bool vio_peer_addr(Vio * vio, char *buf);
/* Remotes in_addr */
void vio_in_addr(Vio *vio, struct in_addr *in);
#ifdef __cplusplus
}
#endif
#endif /* HAVE_VIO */
#endif /* vio_violite_h_ */
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA */
/*
Note that we can't have assertion on file descriptors; The reason for
this is that during mysql shutdown, another thread can close a file
we are working on. In this case we should just return read errors from
the file descriptior.
*/
#include <global.h>
#include <errno.h>
#include <assert.h>
#include <vio.h>
#include <my_sys.h>
#include <my_net.h>
#include <m_string.h>
#ifdef HAVE_POLL
#include <sys/poll.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#if defined(__EMX__)
#define ioctlsocket ioctl
#endif /* defined(__EMX__) */
#if defined(MSDOS) || defined(__WIN__)
#ifdef __WIN__
#undef errno
#undef EINTR
#undef EAGAIN
#define errno WSAGetLastError()
#define EINTR WSAEINTR
#define EAGAIN WSAEINPROGRESS
#endif /* __WIN__ */
#define O_NONBLOCK 1 /* For emulation of fcntl() */
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
#endif
#ifndef __WIN__
#define HANDLE void *
#endif
#ifdef HAVE_OPENSSL
void vio_ssl_delete(st_vio * vio)
{
/* It must be safe to delete null pointers. */
/* This matches the semantics of C++'s delete operator. */
if (vio)
{
if (vio->type != VIO_CLOSED)
vio_close(vio);
my_free((gptr) vio,MYF(0));
}
}
int vio_ssl_errno(st_vio *vio __attribute__((unused)))
{
return errno; /* On Win32 this mapped to WSAGetLastError() */
}
int vio_ssl_read(st_vio * vio, gptr buf, int size)
{
int r;
DBUG_ENTER("vio_ssl_read");
DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
assert(vio->ssl_!= 0);
r = SSL_read(vio->ssl_, buf, size);
#ifndef DBUG_OFF
if ( r< 0)
report_errors();
#endif /* DBUG_OFF */
DBUG_PRINT("exit", ("%d", r));
DBUG_RETURN(r);
}
int vio_ssl_write(st_vio * vio, const gptr buf, int size)
{
int r;
DBUG_ENTER("vio_ssl_write");
DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
assert(vio->ssl_!=0);
r = SSL_write(vio->ssl_, buf, size);
#ifndef DBUG_OFF
if (r<0)
report_errors();
#endif /* DBUG_OFF */
DBUG_PRINT("exit", ("%d", r));
DBUG_RETURN(r);
}
int vio_ssl_fastsend(st_vio * vio __attribute__((unused)))
{
int r=0;
DBUG_ENTER("vio_ssl_fastsend");
#ifdef IPTOS_THROUGHPUT
{
#ifndef __EMX__
int tos = IPTOS_THROUGHPUT;
if (!setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos)))
#endif /* !__EMX__ */
{
int nodelay = 1;
if (setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, (void *) &nodelay,
sizeof(nodelay))) {
DBUG_PRINT("warning",
("Couldn't set socket option for fast send"));
r= -1;
}
}
}
#endif /* IPTOS_THROUGHPUT */
DBUG_PRINT("exit", ("%d", r));
DBUG_RETURN(r);
}
int vio_ssl_keepalive(st_vio* vio, my_bool set_keep_alive)
{
int r=0;
uint opt = 0;
DBUG_ENTER("vio_ssl_keepalive");
DBUG_PRINT("enter", ("sd=%d, set_keep_alive=%d", vio->sd, (int)
set_keep_alive));
if (vio->type != VIO_TYPE_NAMEDPIPE)
{
if (set_keep_alive)
opt = 1;
r = setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
sizeof(opt));
}
DBUG_RETURN(r);
}
my_bool
vio_ssl_should_retry(st_vio * vio __attribute__((unused)))
{
int en = errno;
return en == EAGAIN || en == EINTR || en == EWOULDBLOCK;
}
int vio_ssl_close(st_vio * vio)
{
int r;
DBUG_ENTER("vio_ssl_close");
r=0;
if (vio->ssl_)
{
r = SSL_shutdown(vio->ssl_);
SSL_free(vio->ssl_);
vio->ssl_= 0;
vio->bio_ = 0;
}
if (shutdown(vio->sd,2))
r= -1;
if (closesocket(vio->sd))
r= -1;
if (r)
{
DBUG_PRINT("error", ("close() failed, error: %d",errno));
/* FIXME: error handling (not critical for MySQL) */
}
vio->type= VIO_CLOSED;
vio->sd= -1;
DBUG_RETURN(r);
}
const char *vio_ssl_description(st_vio * vio)
{
return vio->desc;
}
enum enum_vio_type vio_ssl_type(st_vio* vio)
{
return vio->type;
}
my_socket vio_ssl_fd(st_vio* vio)
{
return vio->sd;
}
my_bool vio_ssl_peer_addr(st_vio * vio, char *buf)
{
DBUG_ENTER("vio_ssl_peer_addr");
DBUG_PRINT("enter", ("sd=%d", vio->sd));
if (vio->localhost)
{
strmov(buf,"127.0.0.1");
}
else
{
size_socket addrLen = sizeof(struct sockaddr);
if (getpeername(vio->sd, (struct sockaddr *) (& (vio->remote)),
&addrLen) != 0)
{
DBUG_PRINT("exit", ("getpeername, error: %d", errno));
DBUG_RETURN(1);
}
/* FIXME */
/* my_inet_ntoa(vio->remote.sin_addr,buf); */
}
DBUG_PRINT("exit", ("addr=%s", buf));
DBUG_RETURN(0);
}
void vio_ssl_in_addr(st_vio *vio, struct in_addr *in)
{
DBUG_ENTER("vio_ssl_in_addr");
if (vio->localhost)
bzero((char*) in, sizeof(*in)); /* This should never be executed */
else
*in=vio->remote.sin_addr;
DBUG_VOID_RETURN;
}
/* Return 0 if there is data to be read */
my_bool vio_ssl_poll_read(st_vio *vio,uint timeout)
{
#ifndef HAVE_POLL
return 0;
#else
struct pollfd fds;
int res;
DBUG_ENTER("vio_ssl_poll");
fds.fd=vio->sd;
fds.events=POLLIN;
fds.revents=0;
if ((res=poll(&fds,1,(int) timeout*1000)) <= 0)
{
DBUG_RETURN(res < 0 ? 0 : 1); /* Don't return 1 on errors */
}
DBUG_RETURN(fds.revents & POLLIN ? 0 : 1);
#endif
}
static void
report_errors()
{
unsigned long l;
const char* file;
const char* data;
int line,flags;
DBUG_ENTER("report_errors");
while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
{
char buf[200];
DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
file,line,(flags&ERR_TXT_STRING)?data:"")) ;
}
DBUG_VOID_RETURN;
}
/* FIXME: There are some duplicate code in
* sslaccept()/sslconnect() which maybe can be eliminated
*/
struct st_vio *sslaccept(struct st_VioSSLAcceptorFd* ptr, struct st_vio* sd)
{
DBUG_ENTER("sslaccept");
DBUG_PRINT("enter", ("sd=%s ptr=%p", sd->desc,ptr));
vio_reset(sd,VIO_TYPE_SSL,sd->sd,0,FALSE);
ptr->bio_=0;
sd->ssl_=0;
sd->open_=FALSE;
assert(sd != 0);
assert(ptr != 0);
assert(ptr->ssl_context_ != 0);
if (!(sd->ssl_ = SSL_new(ptr->ssl_context_)))
{
DBUG_PRINT("error", ("SSL_new failure"));
report_errors();
DBUG_RETURN(sd);
}
if (!(ptr->bio_ = BIO_new_socket(sd->sd, BIO_NOCLOSE)))
{
DBUG_PRINT("error", ("BIO_new_socket failure"));
report_errors();
SSL_free(sd->ssl_);
sd->ssl_=0;
DBUG_RETURN(sd);
}
SSL_set_bio(sd->ssl_, ptr->bio_, ptr->bio_);
SSL_set_accept_state(sd->ssl_);
sprintf(ptr->desc_, "VioSSL(%d)", sd->sd);
/* sd->ssl_cip_ = SSL_get_cipher(sd->ssl_); */
sd->open_ = TRUE;
DBUG_RETURN(sd);
}
struct st_vio *sslconnect(struct st_VioSSLConnectorFd* ptr, struct st_vio* sd)
{
DBUG_ENTER("sslconnect");
DBUG_PRINT("enter", ("sd=%s ptr=%p ctx: %p", sd->desc,ptr,ptr->ssl_context_));
vio_reset(sd,VIO_TYPE_SSL,sd->sd,0,FALSE);
ptr->bio_=0;
sd->ssl_=0;
sd->open_=FALSE;
assert(sd != 0);
assert(ptr != 0);
assert(ptr->ssl_context_ != 0);
if (!(sd->ssl_ = SSL_new(ptr->ssl_context_)))
{
DBUG_PRINT("error", ("SSL_new failure"));
report_errors();
DBUG_RETURN(sd);
}
if (!(ptr->bio_ = BIO_new_socket(sd->sd, BIO_NOCLOSE)))
{
DBUG_PRINT("error", ("BIO_new_socket failure"));
report_errors();
SSL_free(sd->ssl_);
sd->ssl_=0;
DBUG_RETURN(sd);
}
SSL_set_bio(sd->ssl_, ptr->bio_, ptr->bio_);
SSL_set_connect_state(sd->ssl_);
/* sprintf(ptr->desc_, "VioSSL(%d)", sd->sd);
sd->ssl_cip_ = SSL_get_cipher(sd->ssl_);*/
sd->open_ = TRUE;
DBUG_RETURN(sd);
}
#endif /* HAVE_OPENSSL */
/*
** Virtual I/O library
** Written by Andrei Errapart <andreie@no.spam.ee>
*/
#include "vio-global.h"
#ifdef VIO_HAVE_OPENSSL #include <global.h>
#include <my_sys.h>
#include <vio.h>
#ifdef __GNUC__ #ifdef HAVE_OPENSSL
#pragma implementation // gcc: Class implementation
#endif
#include <netinet/in.h>
#include <openssl/x509.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/asn1.h>
VIO_NS_BEGIN
#define this_ssl_method my_static_cast(SSL_METHOD*)(this->ssl_method_)
#define this_ssl_context my_static_cast(SSL_CTX*)(this->ssl_context_)
typedef unsigned char* ssl_data_ptr_t;
static bool ssl_algorithms_added = FALSE; static bool ssl_algorithms_added = FALSE;
static bool ssl_error_strings_loaded= FALSE; static bool ssl_error_strings_loaded= FALSE;
static int verify_depth = 0; static int verify_depth = 0;
static int verify_error = X509_V_OK; static int verify_error = X509_V_OK;
static int
vio_verify_callback(int ok, X509_STORE_CTX *ctx) static void
report_errors()
{ {
DBUG_ENTER("vio_verify_callback"); unsigned long l;
DBUG_PRINT("enter", ("ok=%d, ctx=%p", ok, ctx)); const char* file;
char buf[256]; const char* data;
X509* err_cert; int line,flags;
int err,depth;
err_cert=X509_STORE_CTX_get_current_cert(ctx); DBUG_ENTER("report_errors");
err= X509_STORE_CTX_get_error(ctx);
depth= X509_STORE_CTX_get_error_depth(ctx);
X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buff)); while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
if (!ok)
{
DBUG_PRINT("error",("verify error:num=%d:%s\n",err,
X509_verify_cert_error_string(err)));
if (verify_depth >= depth)
{
ok=1;
verify_error=X509_V_OK;
}
else
{ {
ok=0; char buf[200];
verify_error=X509_V_ERR_CERT_CHAIN_TOO_LONG; DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
} file,line,(flags&ERR_TXT_STRING)?data:"")) ;
}
switch (ctx->error) {
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,256);
DBUG_PRINT("info",("issuer= %s\n",buf));
break;
case X509_V_ERR_CERT_NOT_YET_VALID:
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
DBUG_PRINT("error", ("notBefore"));
//ASN1_TIME_print_fp(stderr,X509_get_notBefore(ctx->current_cert));
break;
case X509_V_ERR_CERT_HAS_EXPIRED:
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
DBUG_PRINT("error", ("notAfter error"));
//ASN1_TIME_print_fp(stderr,X509_get_notAfter(ctx->current_cert));
break;
} }
DBUG_PRINT("exit", ("r=%d", ok)); DBUG_VOID_RETURN;
DBUG_RETURN(ok);
} }
...@@ -118,36 +71,90 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file) ...@@ -118,36 +71,90 @@ vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file)
DBUG_RETURN(1); DBUG_RETURN(1);
} }
static int
vio_verify_callback(int ok, X509_STORE_CTX *ctx)
{
char buf[256];
X509* err_cert;
int err,depth;
DBUG_ENTER("vio_verify_callback");
DBUG_PRINT("enter", ("ok=%d, ctx=%p", ok, ctx));
err_cert=X509_STORE_CTX_get_current_cert(ctx);
err= X509_STORE_CTX_get_error(ctx);
depth= X509_STORE_CTX_get_error_depth(ctx);
X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buf));
if (!ok)
{
DBUG_PRINT("error",("verify error:num=%d:%s\n",err,
X509_verify_cert_error_string(err)));
if (verify_depth >= depth)
{
ok=1;
verify_error=X509_V_OK;
}
else
{
ok=0;
verify_error=X509_V_ERR_CERT_CHAIN_TOO_LONG;
}
}
switch (ctx->error) {
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,256);
DBUG_PRINT("info",("issuer= %s\n",buf));
break;
case X509_V_ERR_CERT_NOT_YET_VALID:
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
DBUG_PRINT("error", ("notBefore"));
/*ASN1_TIME_print_fp(stderr,X509_get_notBefore(ctx->current_cert));*/
break;
case X509_V_ERR_CERT_HAS_EXPIRED:
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
DBUG_PRINT("error", ("notAfter error"));
/*ASN1_TIME_print_fp(stderr,X509_get_notAfter(ctx->current_cert));*/
break;
}
DBUG_PRINT("exit", ("r=%d", ok));
DBUG_RETURN(ok);
}
/************************ VioSSLConnectorFd **********************************/ /************************ VioSSLConnectorFd **********************************/
VioSSLConnectorFd::VioSSLConnectorFd(const char* key_file, struct st_VioSSLConnectorFd* new_VioSSLConnectorFd(const char* key_file,
const char* cert_file, const char* cert_file,
const char* ca_file, const char* ca_file,
const char* ca_path) const char* ca_path)
:ssl_context_(0),ssl_method_(0)
{ {
DBUG_ENTER("VioSSLConnectorFd::VioSSLConnectorFd"); int verify = SSL_VERIFY_PEER;
struct st_VioSSLConnectorFd* ptr;
DBUG_ENTER("new_VioSSLConnectorFd");
DBUG_PRINT("enter", DBUG_PRINT("enter",
("this=%p, key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s", ("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s",
this, key_file, cert_file, ca_path, ca_file)); key_file, cert_file, ca_path, ca_file));
ptr=(struct st_VioSSLConnectorFd*)my_malloc(sizeof(struct st_VioSSLConnectorFd),MYF(0));
ptr->ssl_context_=0;
ptr->ssl_method_=0;
/* FIXME: constants! */ /* FIXME: constants! */
int verify = SSL_VERIFY_PEER;
if (!ssl_algorithms_added) if (!ssl_algorithms_added)
{ {
DBUG_PRINT("info", ("todo: SSLeay_add_ssl_algorithms()")); DBUG_PRINT("info", ("todo: SSLeay_add_ssl_algorithms()"));
ssl_algorithms_added = true; ssl_algorithms_added = TRUE;
SSLeay_add_ssl_algorithms(); SSLeay_add_ssl_algorithms();
} }
if (!ssl_error_strings_loaded) if (!ssl_error_strings_loaded)
{ {
DBUG_PRINT("info", ("todo:SSL_load_error_strings()")); DBUG_PRINT("info", ("todo:SSL_load_error_strings()"));
ssl_error_strings_loaded = true; ssl_error_strings_loaded = TRUE;
SSL_load_error_strings(); SSL_load_error_strings();
} }
ssl_method_ = SSLv3_client_method(); ptr->ssl_method_ = SSLv3_client_method();
ssl_context_ = SSL_CTX_new(this_ssl_method); ptr->ssl_context_ = SSL_CTX_new(ptr->ssl_method_);
if (ssl_context_ == 0) DBUG_PRINT("info", ("ssl_context_: %p",ptr->ssl_context_));
if (ptr->ssl_context_ == 0)
{ {
DBUG_PRINT("error", ("SSL_CTX_new failed")); DBUG_PRINT("error", ("SSL_CTX_new failed"));
report_errors(); report_errors();
...@@ -158,107 +165,69 @@ VioSSLConnectorFd::VioSSLConnectorFd(const char* key_file, ...@@ -158,107 +165,69 @@ VioSSLConnectorFd::VioSSLConnectorFd(const char* key_file,
* SSL_CTX_set_info_callback * SSL_CTX_set_info_callback
* SSL_CTX_set_cipher_list * SSL_CTX_set_cipher_list
*/ */
SSL_CTX_set_verify(this_ssl_context, verify, vio_verify_callback); SSL_CTX_set_verify(ptr->ssl_context_, verify, vio_verify_callback);
if (vio_set_cert_stuff(this_ssl_context, cert_file, key_file) == -1) if (vio_set_cert_stuff(ptr->ssl_context_, cert_file, key_file) == -1)
{ {
DBUG_PRINT("error", ("vio_set_cert_stuff failed")); DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
report_errors(); report_errors();
goto ctor_failure; goto ctor_failure;
} }
if (SSL_CTX_load_verify_locations( this_ssl_context, ca_file,ca_path)==0) if (SSL_CTX_load_verify_locations( ptr->ssl_context_, ca_file,ca_path)==0)
{ {
DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed")); DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
if (SSL_CTX_set_default_verify_paths(this_ssl_context)==0) if (SSL_CTX_set_default_verify_paths(ptr->ssl_context_)==0)
{ {
DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed")); DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed"));
report_errors(); report_errors();
goto ctor_failure; goto ctor_failure;
} }
} }
DBUG_VOID_RETURN; DBUG_RETURN(ptr);
ctor_failure: ctor_failure:
DBUG_PRINT("exit", ("there was an error")); DBUG_PRINT("exit", ("there was an error"));
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
VioSSLConnectorFd::~VioSSLConnectorFd()
{
DBUG_ENTER("VioSSLConnectorFd::~VioSSLConnectorFd");
DBUG_PRINT("enter", ("this=%p", this));
if (ssl_context_!=0)
SSL_CTX_free(this_ssl_context);
DBUG_VOID_RETURN;
}
VioSSL* VioSSLConnectorFd::connect( int fd)
{
DBUG_ENTER("VioSSLConnectorFd::connect");
DBUG_PRINT("enter", ("this=%p, fd=%d", this, fd));
DBUG_RETURN(new VioSSL(fd, ssl_context_, VioSSL::state_connect));
}
VioSSL*
VioSSLConnectorFd::connect( VioSocket* sd)
{
DBUG_ENTER("VioSSLConnectorFd::connect");
DBUG_PRINT("enter", ("this=%p, sd=%s", this, sd->description()));
DBUG_RETURN(new VioSSL(sd, ssl_context_, VioSSL::state_connect));
}
void
VioSSLConnectorFd::report_errors()
{
unsigned long l;
const char* file;
const char* data;
int line,flags;
DBUG_ENTER("VioSSLConnectorFd::report_errors");
DBUG_PRINT("enter", ("this=%p", this));
while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
{
char buf[200];
DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
file,line,(flags&ERR_TXT_STRING)?data:"")) ;
}
DBUG_VOID_RETURN;
}
/************************ VioSSLAcceptorFd **********************************/ /************************ VioSSLAcceptorFd **********************************/
VioSSLAcceptorFd::VioSSLAcceptorFd(const char* key_file, struct st_VioSSLAcceptorFd*
new_VioSSLAcceptorFd(const char* key_file,
const char* cert_file, const char* cert_file,
const char* ca_file, const char* ca_file,
const char* ca_path) const char* ca_path)
:ssl_context_(0), ssl_method_(0)
{ {
DBUG_ENTER("VioSSLAcceptorFd::VioSSLAcceptorFd");
DBUG_PRINT("enter",
("this=%p, key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s",
this, key_file, cert_file, ca_path, ca_file));
/* FIXME: constants! */
int verify = (SSL_VERIFY_PEER | int verify = (SSL_VERIFY_PEER |
SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_FAIL_IF_NO_PEER_CERT |
SSL_VERIFY_CLIENT_ONCE); SSL_VERIFY_CLIENT_ONCE);
session_id_context_ = static_cast<vio_ptr>(this);
struct st_VioSSLAcceptorFd* ptr;
DBUG_ENTER("new_VioSSLAcceptorFd");
DBUG_PRINT("enter",
("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s",
key_file, cert_file, ca_path, ca_file));
ptr=(struct st_VioSSLAcceptorFd*)my_malloc(sizeof(struct st_VioSSLAcceptorFd),MYF(0));
ptr->ssl_context_=0;
ptr->ssl_method_=0;
/* FIXME: constants! */
ptr->session_id_context_ = ptr;
if (!ssl_algorithms_added) if (!ssl_algorithms_added)
{ {
DBUG_PRINT("info", ("todo: SSLeay_add_ssl_algorithms()")); DBUG_PRINT("info", ("todo: SSLeay_add_ssl_algorithms()"));
ssl_algorithms_added = true; ssl_algorithms_added = TRUE;
SSLeay_add_ssl_algorithms(); SSLeay_add_ssl_algorithms();
} }
if (!ssl_error_strings_loaded) if (!ssl_error_strings_loaded)
{ {
DBUG_PRINT("info", ("todo: SSL_load_error_strings()")); DBUG_PRINT("info", ("todo: SSL_load_error_strings()"));
ssl_error_strings_loaded = true; ssl_error_strings_loaded = TRUE;
SSL_load_error_strings(); SSL_load_error_strings();
} }
ssl_method_ = SSLv3_server_method(); ptr->ssl_method_ = SSLv3_server_method();
ssl_context_ = SSL_CTX_new(this_ssl_method); ptr->ssl_context_ = SSL_CTX_new(ptr->ssl_method_);
if (ssl_context_==0) if (ptr->ssl_context_==0)
{ {
DBUG_PRINT("error", ("SSL_CTX_new failed")); DBUG_PRINT("error", ("SSL_CTX_new failed"));
report_errors(); report_errors();
...@@ -268,93 +237,40 @@ VioSSLAcceptorFd::VioSSLAcceptorFd(const char* key_file, ...@@ -268,93 +237,40 @@ VioSSLAcceptorFd::VioSSLAcceptorFd(const char* key_file,
* SSL_CTX_set_quiet_shutdown(ctx,1); * SSL_CTX_set_quiet_shutdown(ctx,1);
* *
*/ */
SSL_CTX_sess_set_cache_size(this_ssl_context,128); SSL_CTX_sess_set_cache_size(ptr->ssl_context_,128);
/* DH? /* DH?
*/ */
SSL_CTX_set_verify(this_ssl_context, verify, vio_verify_callback); SSL_CTX_set_verify(ptr->ssl_context_, verify, vio_verify_callback);
/* SSL_CTX_set_session_id_context(ptr->ssl_context_,(const uchar*)&(ptr->session_id_context_),sizeof(ptr->session_id_context_));
* Double cast needed at least for egcs-1.1.2 to
* supress warnings:
* 1) ANSI C++ blaah implicit cast from 'void*' to 'unsigned char*'
* 2) static_cast from 'void**' to 'unsigned char*'
* Wish I had a copy of standard handy...
*/
SSL_CTX_set_session_id_context(this_ssl_context,
my_static_cast(ssl_data_ptr_t)
(my_static_cast(void*)(&session_id_context_)),
sizeof(session_id_context_));
/* /*
* SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile)); * SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile));
*/ */
if (vio_set_cert_stuff(this_ssl_context, cert_file, key_file) == -1) if (vio_set_cert_stuff(ptr->ssl_context_, cert_file, key_file) == -1)
{ {
DBUG_PRINT("error", ("vio_set_cert_stuff failed")); DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
report_errors(); report_errors();
goto ctor_failure; goto ctor_failure;
} }
if (SSL_CTX_load_verify_locations( this_ssl_context, ca_file, ca_path)==0) if (SSL_CTX_load_verify_locations( ptr->ssl_context_, ca_file, ca_path)==0)
{ {
DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed")); DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
if (SSL_CTX_set_default_verify_paths(this_ssl_context)==0) if (SSL_CTX_set_default_verify_paths(ptr->ssl_context_)==0)
{ {
DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed")); DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed"));
report_errors(); report_errors();
goto ctor_failure; goto ctor_failure;
} }
} }
DBUG_VOID_RETURN; DBUG_RETURN(ptr);
ctor_failure: ctor_failure:
DBUG_PRINT("exit", ("there was an error")); DBUG_PRINT("exit", ("there was an error"));
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
VioSSLAcceptorFd::~VioSSLAcceptorFd()
{
DBUG_ENTER("VioSSLAcceptorFd::~VioSSLAcceptorFd");
DBUG_PRINT("enter", ("this=%p", this));
if (ssl_context_!=0)
SSL_CTX_free(this_ssl_context);
DBUG_VOID_RETURN;
}
VioSSL*
VioSSLAcceptorFd::accept(int fd)
{
DBUG_ENTER("VioSSLAcceptorFd::accept");
DBUG_PRINT("enter", ("this=%p, fd=%d", this, fd));
DBUG_RETURN(new VioSSL(fd, ssl_context_, VioSSL::state_accept));
}
VioSSL*
VioSSLAcceptorFd::accept(VioSocket* sd)
{
DBUG_ENTER("VioSSLAcceptorFd::accept");
DBUG_PRINT("enter", ("this=%p, sd=%s", this, sd->description()));
DBUG_RETURN(new VioSSL(sd, ssl_context_, VioSSL::state_accept));
}
void
VioSSLAcceptorFd::report_errors()
{
unsigned long l;
const char* file;
const char* data;
int line,flags;
DBUG_ENTER("VioSSLConnectorFd::report_errors"); #endif /* HAVE_OPENSSL */
DBUG_PRINT("enter", ("this=%p", this));
while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
{
char buf[200];
DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
file,line,(flags&ERR_TXT_STRING)?data:"")) ;
}
DBUG_VOID_RETURN;
}
VIO_NS_END
#endif /* VIO_HAVE_OPENSSL */
...@@ -22,22 +22,23 @@ ...@@ -22,22 +22,23 @@
the file descriptior. the file descriptior.
*/ */
#define DONT_MAP_VIO
#include <global.h> #include <global.h>
#ifndef HAVE_VIO /* is Vio suppored by the Vio lib ? */
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
#include <violite.h> #include <vio.h>
#include <my_sys.h> #include <my_sys.h>
#include <my_net.h> #include <my_net.h>
#include <m_string.h> #include <m_string.h>
#ifdef HAVE_POLL #ifdef HAVE_POLL
#include <sys/poll.h> #include <sys/poll.h>
#endif #endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#if defined(__EMX__) #if defined(__EMX__)
#include <sys/ioctl.h>
#define ioctlsocket ioctl #define ioctlsocket ioctl
#endif /* defined(__EMX__) */ #endif /* defined(__EMX__) */
...@@ -60,82 +61,7 @@ ...@@ -60,82 +61,7 @@
#define HANDLE void * #define HANDLE void *
#endif #endif
struct st_vio void vio_delete(st_vio* vio)
{
my_socket sd; /* my_socket - real or imaginary */
HANDLE hPipe;
my_bool localhost; /* Are we from localhost? */
int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */
struct sockaddr_in local; /* Local internet address */
struct sockaddr_in remote; /* Remote internet address */
enum enum_vio_type type; /* Type of connection */
char desc[30]; /* String description */
};
typedef void *vio_ptr;
typedef char *vio_cstring;
/*
* Helper to fill most of the Vio* with defaults.
*/
static void vio_reset(Vio* vio, enum enum_vio_type type,
my_socket sd, HANDLE hPipe,
my_bool localhost)
{
bzero((char*) vio, sizeof(*vio));
vio->type = type;
vio->sd = sd;
vio->hPipe = hPipe;
vio->localhost= localhost;
}
/* Open the socket or TCP/IP connection and read the fnctl() status */
Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
{
Vio *vio;
DBUG_ENTER("vio_new");
DBUG_PRINT("enter", ("sd=%d", sd));
if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
{
vio_reset(vio, type, sd, 0, localhost);
sprintf(vio->desc,
(vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"),
vio->sd);
#if !defined(___WIN__) && !defined(__EMX__)
#if !defined(NO_FCNTL_NONBLOCK)
vio->fcntl_mode = fcntl(sd, F_GETFL);
#endif
#else /* !defined(__WIN__) && !defined(__EMX__) */
{
/* set to blocking mode by default */
ulong arg=0, r;
r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg, sizeof(arg));
}
#endif
}
DBUG_RETURN(vio);
}
#ifdef __WIN__
Vio *vio_new_win32pipe(HANDLE hPipe)
{
Vio *vio;
DBUG_ENTER("vio_new_handle");
if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
{
vio_reset(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, TRUE);
strmov(vio->desc, "named pipe");
}
DBUG_RETURN(vio);
}
#endif
void vio_delete(Vio * vio)
{ {
/* It must be safe to delete null pointers. */ /* It must be safe to delete null pointers. */
/* This matches the semantics of C++'s delete operator. */ /* This matches the semantics of C++'s delete operator. */
...@@ -147,13 +73,13 @@ void vio_delete(Vio * vio) ...@@ -147,13 +73,13 @@ void vio_delete(Vio * vio)
} }
} }
int vio_errno(Vio *vio __attribute__((unused))) int vio_errno(st_vio *vio __attribute__((unused)))
{ {
return errno; /* On Win32 this mapped to WSAGetLastError() */ return errno; /* On Win32 this mapped to WSAGetLastError() */
} }
int vio_read(Vio * vio, gptr buf, int size) int vio_read(st_vio * vio, gptr buf, int size)
{ {
int r; int r;
DBUG_ENTER("vio_read"); DBUG_ENTER("vio_read");
...@@ -182,7 +108,7 @@ int vio_read(Vio * vio, gptr buf, int size) ...@@ -182,7 +108,7 @@ int vio_read(Vio * vio, gptr buf, int size)
} }
int vio_write(Vio * vio, const gptr buf, int size) int vio_write(st_vio * vio, const gptr buf, int size)
{ {
int r; int r;
DBUG_ENTER("vio_write"); DBUG_ENTER("vio_write");
...@@ -210,7 +136,7 @@ int vio_write(Vio * vio, const gptr buf, int size) ...@@ -210,7 +136,7 @@ int vio_write(Vio * vio, const gptr buf, int size)
} }
int vio_blocking(Vio * vio, my_bool set_blocking_mode) int vio_blocking(st_vio * vio, my_bool set_blocking_mode)
{ {
int r=0; int r=0;
DBUG_ENTER("vio_blocking"); DBUG_ENTER("vio_blocking");
...@@ -255,7 +181,7 @@ int vio_blocking(Vio * vio, my_bool set_blocking_mode) ...@@ -255,7 +181,7 @@ int vio_blocking(Vio * vio, my_bool set_blocking_mode)
} }
my_bool my_bool
vio_is_blocking(Vio * vio) vio_is_blocking(st_vio * vio)
{ {
my_bool r; my_bool r;
DBUG_ENTER("vio_is_blocking"); DBUG_ENTER("vio_is_blocking");
...@@ -265,7 +191,7 @@ vio_is_blocking(Vio * vio) ...@@ -265,7 +191,7 @@ vio_is_blocking(Vio * vio)
} }
int vio_fastsend(Vio * vio __attribute__((unused))) int vio_fastsend(st_vio * vio __attribute__((unused)))
{ {
int r=0; int r=0;
DBUG_ENTER("vio_fastsend"); DBUG_ENTER("vio_fastsend");
...@@ -291,7 +217,7 @@ int vio_fastsend(Vio * vio __attribute__((unused))) ...@@ -291,7 +217,7 @@ int vio_fastsend(Vio * vio __attribute__((unused)))
DBUG_RETURN(r); DBUG_RETURN(r);
} }
int vio_keepalive(Vio* vio, my_bool set_keep_alive) int vio_keepalive(st_vio* vio, my_bool set_keep_alive)
{ {
int r=0; int r=0;
uint opt = 0; uint opt = 0;
...@@ -310,14 +236,14 @@ int vio_keepalive(Vio* vio, my_bool set_keep_alive) ...@@ -310,14 +236,14 @@ int vio_keepalive(Vio* vio, my_bool set_keep_alive)
my_bool my_bool
vio_should_retry(Vio * vio __attribute__((unused))) vio_should_retry(st_vio * vio __attribute__((unused)))
{ {
int en = errno; int en = errno;
return en == EAGAIN || en == EINTR || en == EWOULDBLOCK; return en == EAGAIN || en == EINTR || en == EWOULDBLOCK;
} }
int vio_close(Vio * vio) int vio_close(st_vio * vio)
{ {
int r; int r;
DBUG_ENTER("vio_close"); DBUG_ENTER("vio_close");
...@@ -350,23 +276,23 @@ int vio_close(Vio * vio) ...@@ -350,23 +276,23 @@ int vio_close(Vio * vio)
} }
const char *vio_description(Vio * vio) const char *vio_description(st_vio * vio)
{ {
return vio->desc; return vio->desc;
} }
enum enum_vio_type vio_type(Vio* vio) enum enum_vio_type vio_type(st_vio* vio)
{ {
return vio->type; return vio->type;
} }
my_socket vio_fd(Vio* vio) my_socket vio_fd(st_vio* vio)
{ {
return vio->sd; return vio->sd;
} }
my_bool vio_peer_addr(Vio * vio, char *buf) my_bool vio_peer_addr(st_vio * vio, char *buf)
{ {
DBUG_ENTER("vio_peer_addr"); DBUG_ENTER("vio_peer_addr");
DBUG_PRINT("enter", ("sd=%d", vio->sd)); DBUG_PRINT("enter", ("sd=%d", vio->sd));
...@@ -383,14 +309,15 @@ my_bool vio_peer_addr(Vio * vio, char *buf) ...@@ -383,14 +309,15 @@ my_bool vio_peer_addr(Vio * vio, char *buf)
DBUG_PRINT("exit", ("getpeername, error: %d", errno)); DBUG_PRINT("exit", ("getpeername, error: %d", errno));
DBUG_RETURN(1); DBUG_RETURN(1);
} }
my_inet_ntoa(vio->remote.sin_addr,buf); /* FIXME */
/* my_inet_ntoa(vio->remote.sin_addr,buf); */
} }
DBUG_PRINT("exit", ("addr=%s", buf)); DBUG_PRINT("exit", ("addr=%s", buf));
DBUG_RETURN(0); DBUG_RETURN(0);
} }
void vio_in_addr(Vio *vio, struct in_addr *in) void vio_in_addr(st_vio *vio, struct in_addr *in)
{ {
DBUG_ENTER("vio_in_addr"); DBUG_ENTER("vio_in_addr");
if (vio->localhost) if (vio->localhost)
...@@ -403,7 +330,7 @@ void vio_in_addr(Vio *vio, struct in_addr *in) ...@@ -403,7 +330,7 @@ void vio_in_addr(Vio *vio, struct in_addr *in)
/* Return 0 if there is data to be read */ /* Return 0 if there is data to be read */
my_bool vio_poll_read(Vio *vio,uint timeout) my_bool vio_poll_read(st_vio *vio,uint timeout)
{ {
#ifndef HAVE_POLL #ifndef HAVE_POLL
return 0; return 0;
...@@ -422,4 +349,3 @@ my_bool vio_poll_read(Vio *vio,uint timeout) ...@@ -422,4 +349,3 @@ my_bool vio_poll_read(Vio *vio,uint timeout)
#endif #endif
} }
#endif /* HAVE_VIO */
/*
** Virtual I/O library
** Written by Andrei Errapart <andreie@no.spam.ee>
*/
/*
* Some typedefs to external types.
*/
#ifndef vio_viotypes_h_
#define vio_viotypes_h_
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
typedef int vio_bool_t;
typedef void* vio_ptr_t;
#ifdef __cplusplus
VIO_NS_BEGIN
typedef vio_ptr_t vio_ptr;
typedef char* vio_cstring;
typedef int32_t vio_int32;
typedef u_int32_t vio_uint32;
typedef vio_bool_t vio_bool;
VIO_NS_END
#endif /* __cplusplus */
#endif /* vio_types_h_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment