aboutsummaryrefslogtreecommitdiff
path: root/externals/mysql/vio
diff options
context:
space:
mode:
authorXanadu <none@none>2010-07-20 02:49:28 +0200
committerXanadu <none@none>2010-07-20 02:49:28 +0200
commit79622802f397258ee0f34327ba3ae6977ca3e7ff (patch)
tree1868946c234ab9ee256a6b7766a15713eae94235 /externals/mysql/vio
parent7dd2dc91816ab8b3bc3b99a1b1c99c7ea314d5a8 (diff)
parentf906976837502fa5aa81b982b901d1509f5aa0c4 (diff)
Merge. Revision history for source files should be all back now.
--HG-- branch : trunk rename : sql/CMakeLists.txt => sql/tools/CMakeLists.txt rename : src/server/game/Pools/PoolHandler.cpp => src/server/game/Pools/PoolMgr.cpp rename : src/server/game/Pools/PoolHandler.h => src/server/game/Pools/PoolMgr.h rename : src/server/game/PrecompiledHeaders/NixCorePCH.cpp => src/server/game/PrecompiledHeaders/gamePCH.cpp rename : src/server/game/PrecompiledHeaders/NixCorePCH.h => src/server/game/PrecompiledHeaders/gamePCH.h
Diffstat (limited to 'externals/mysql/vio')
-rw-r--r--externals/mysql/vio/test-ssl.c149
-rw-r--r--externals/mysql/vio/test-sslclient.c101
-rw-r--r--externals/mysql/vio/test-sslserver.c155
-rw-r--r--externals/mysql/vio/vio.c242
-rw-r--r--externals/mysql/vio/vio_priv.h46
-rw-r--r--externals/mysql/vio/viosocket.c714
-rw-r--r--externals/mysql/vio/viossl.c279
-rw-r--r--externals/mysql/vio/viosslfactories.c385
-rw-r--r--externals/mysql/vio/viotest-ssl.c151
-rw-r--r--externals/mysql/vio/viotest-sslconnect.cc80
-rw-r--r--externals/mysql/vio/viotest.cc47
11 files changed, 2349 insertions, 0 deletions
diff --git a/externals/mysql/vio/test-ssl.c b/externals/mysql/vio/test-ssl.c
new file mode 100644
index 00000000000..855dc5fbb3e
--- /dev/null
+++ b/externals/mysql/vio/test-ssl.c
@@ -0,0 +1,149 @@
+/* Copyright (C) 2000 MySQL 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; version 2 of the License.
+
+ 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 */
+
+#include <my_global.h>
+#if defined(HAVE_OPENSSL) && !defined(__NETWARE__)
+#include <my_sys.h>
+#include <m_string.h>
+#include <m_ctype.h>
+#include "mysql.h"
+#include "errmsg.h"
+#include <my_dir.h>
+#include <my_getopt.h>
+#include <signal.h>
+#include <violite.h>
+
+const char *VER="0.2";
+
+
+#ifndef DBUG_OFF
+const char *default_dbug_option="d:t:O,-";
+#endif
+
+void
+fatal_error( const char* r)
+{
+ perror(r);
+ exit(0);
+}
+
+void
+print_usage()
+{
+ printf("viossl-test: testing SSL virtual IO. Usage:\n");
+ printf("viossl-test server-key server-cert client-key client-cert [CAfile] [CApath]\n");
+}
+
+
+int
+main(int argc, char** argv)
+{
+ char* server_key = 0, *server_cert = 0;
+ char* client_key = 0, *client_cert = 0;
+ char* ca_file = 0, *ca_path = 0;
+ char* cipher=0;
+ int child_pid,sv[2];
+ my_bool unused;
+ struct st_VioSSLFd* ssl_acceptor= 0;
+ struct st_VioSSLFd* ssl_connector= 0;
+ Vio* client_vio=0, *server_vio=0;
+ MY_INIT(argv[0]);
+ DBUG_PROCESS(argv[0]);
+ DBUG_PUSH(default_dbug_option);
+
+ if (argc<5)
+ {
+ print_usage();
+ return 1;
+ }
+
+ server_key = argv[1];
+ server_cert = argv[2];
+ client_key = argv[3];
+ client_cert = argv[4];
+ if (argc>5)
+ ca_file = argv[5];
+ if (argc>6)
+ ca_path = argv[6];
+ printf("Server key/cert : %s/%s\n", server_key, server_cert);
+ printf("Client key/cert : %s/%s\n", client_key, client_cert);
+ if (ca_file!=0)
+ printf("CAfile : %s\n", ca_file);
+ if (ca_path!=0)
+ printf("CApath : %s\n", ca_path);
+
+
+ if (socketpair(PF_UNIX, SOCK_STREAM, IPPROTO_IP, sv)==-1)
+ fatal_error("socketpair");
+
+ ssl_acceptor = new_VioSSLAcceptorFd(server_key, server_cert, ca_file,
+ ca_path, cipher);
+ ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file,
+ ca_path, cipher);
+
+ client_vio = (struct st_vio*)my_malloc(sizeof(struct st_vio),MYF(0));
+ client_vio->sd = sv[0];
+ client_vio->vioblocking(client_vio, 0, &unused);
+ sslconnect(ssl_connector,client_vio,60L);
+ server_vio = (struct st_vio*)my_malloc(sizeof(struct st_vio),MYF(0));
+ server_vio->sd = sv[1];
+ server_vio->vioblocking(client_vio, 0, &unused);
+ sslaccept(ssl_acceptor,server_vio,60L);
+
+ printf("Socketpair: %d , %d\n", client_vio->sd, server_vio->sd);
+
+ child_pid = fork();
+ if (child_pid==-1) {
+ my_free((uchar*)ssl_acceptor,MYF(0));
+ my_free((uchar*)ssl_connector,MYF(0));
+ fatal_error("fork");
+ }
+ if (child_pid==0)
+ {
+ /* child, therefore, client */
+ char xbuf[100];
+ int r = vio_read(client_vio,xbuf, sizeof(xbuf));
+ if (r<=0) {
+ my_free((uchar*)ssl_acceptor,MYF(0));
+ my_free((uchar*)ssl_connector,MYF(0));
+ fatal_error("client:SSL_read");
+ }
+ xbuf[r] = 0;
+ printf("client:got %s\n", xbuf);
+ my_free((uchar*)client_vio,MYF(0));
+ my_free((uchar*)ssl_acceptor,MYF(0));
+ my_free((uchar*)ssl_connector,MYF(0));
+ }
+ else
+ {
+ const char* s = "Huhuhuh";
+ int r = vio_write(server_vio,(uchar*)s, strlen(s));
+ if (r<=0) {
+ my_free((uchar*)ssl_acceptor,MYF(0));
+ my_free((uchar*)ssl_connector,MYF(0));
+ fatal_error("server:SSL_write");
+ }
+ my_free((uchar*)server_vio,MYF(0));
+ my_free((uchar*)ssl_acceptor,MYF(0));
+ my_free((uchar*)ssl_connector,MYF(0));
+ }
+ return 0;
+}
+#else /* HAVE_OPENSSL */
+
+int main() {
+return 0;
+}
+#endif /* HAVE_OPENSSL */
diff --git a/externals/mysql/vio/test-sslclient.c b/externals/mysql/vio/test-sslclient.c
new file mode 100644
index 00000000000..e1b8461397b
--- /dev/null
+++ b/externals/mysql/vio/test-sslclient.c
@@ -0,0 +1,101 @@
+/* Copyright (C) 2000 MySQL 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; version 2 of the License.
+
+ 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 */
+
+#include <my_global.h>
+#ifdef HAVE_OPENSSL
+#include <my_sys.h>
+#include <m_string.h>
+#include <m_ctype.h>
+#include "mysql.h"
+#include "errmsg.h"
+#include <my_dir.h>
+#include <my_getopt.h>
+#include <signal.h>
+#include <violite.h>
+
+const char *VER="0.2";
+
+
+#ifndef DBUG_OFF
+const char *default_dbug_option="d:t:O,-";
+#endif
+
+void
+fatal_error( const char* r)
+{
+ perror(r);
+ exit(0);
+}
+
+int
+main( int argc __attribute__((unused)),
+ char** argv)
+{
+ char client_key[] = "../SSL/client-key.pem", client_cert[] = "../SSL/client-cert.pem";
+ char ca_file[] = "../SSL/cacert.pem", *ca_path = 0, *cipher=0;
+ struct st_VioSSLFd* ssl_connector= 0;
+ struct sockaddr_in sa;
+ Vio* client_vio=0;
+ int err;
+ char xbuf[100]="Ohohhhhoh1234";
+ MY_INIT(argv[0]);
+ DBUG_PROCESS(argv[0]);
+ DBUG_PUSH(default_dbug_option);
+
+ printf("Client key/cert : %s/%s\n", client_key, client_cert);
+ if (ca_file!=0)
+ printf("CAfile : %s\n", ca_file);
+ if (ca_path!=0)
+ printf("CApath : %s\n", ca_path);
+
+ ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file, ca_path, cipher);
+ if(!ssl_connector) {
+ fatal_error("client:new_VioSSLConnectorFd failed");
+ }
+
+ /* ----------------------------------------------- */
+ /* Create a socket and connect to server using normal socket calls. */
+
+ client_vio = vio_new(socket (AF_INET, SOCK_STREAM, 0), VIO_TYPE_TCPIP, TRUE);
+
+ memset (&sa, '\0', sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_addr.s_addr = inet_addr ("127.0.0.1"); /* Server IP */
+ sa.sin_port = htons (1111); /* Server Port number */
+
+ err = connect(client_vio->sd, (struct sockaddr*) &sa,
+ sizeof(sa));
+
+ /* ----------------------------------------------- */
+ /* Now we have TCP conncetion. Start SSL negotiation. */
+ read(client_vio->sd,xbuf, sizeof(xbuf));
+ sslconnect(ssl_connector,client_vio,60L);
+ err = vio_read(client_vio,xbuf, sizeof(xbuf));
+ if (err<=0) {
+ my_free((uchar*)ssl_connector,MYF(0));
+ fatal_error("client:SSL_read");
+ }
+ xbuf[err] = 0;
+ printf("client:got %s\n", xbuf);
+ my_free((uchar*)client_vio,MYF(0));
+ my_free((uchar*)ssl_connector,MYF(0));
+ return 0;
+}
+#else /* HAVE_OPENSSL */
+
+int main() {
+return 0;
+}
+#endif /* HAVE_OPENSSL */
diff --git a/externals/mysql/vio/test-sslserver.c b/externals/mysql/vio/test-sslserver.c
new file mode 100644
index 00000000000..8877dd3cbc8
--- /dev/null
+++ b/externals/mysql/vio/test-sslserver.c
@@ -0,0 +1,155 @@
+/* Copyright (C) 2000 MySQL 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; version 2 of the License.
+
+ 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 */
+
+#include <my_global.h>
+#ifdef HAVE_OPENSSL
+#include <my_sys.h>
+#include <m_string.h>
+#include <m_ctype.h>
+#include "mysql.h"
+#include "errmsg.h"
+#include <my_dir.h>
+#include <my_getopt.h>
+#include <signal.h>
+#include <violite.h>
+
+const char *VER="0.2";
+
+
+#ifndef DBUG_OFF
+const char *default_dbug_option="d:t:O,-";
+#endif
+
+#if 0
+static void
+fatal_error( const char* r)
+{
+ perror(r);
+ exit(0);
+}
+#endif
+
+typedef struct {
+ int sd;
+ struct st_VioSSLFd* ssl_acceptor;
+} TH_ARGS;
+
+static void
+do_ssl_stuff( TH_ARGS* args)
+{
+ const char* s = "Huhuhuhuuu";
+ Vio* server_vio;
+ int err;
+ DBUG_ENTER("do_ssl_stuff");
+
+ server_vio = vio_new(args->sd, VIO_TYPE_TCPIP, TRUE);
+
+ /* ----------------------------------------------- */
+ /* TCP connection is ready. Do server side SSL. */
+
+ err = write(server_vio->sd,(uchar*)s, strlen(s));
+ sslaccept(args->ssl_acceptor,server_vio,60L);
+ err = server_vio->write(server_vio,(uchar*)s, strlen(s));
+ DBUG_VOID_RETURN;
+}
+
+static void*
+client_thread( void* arg)
+{
+ my_thread_init();
+ do_ssl_stuff((TH_ARGS*)arg);
+ return 0;
+}
+
+int
+main(int argc __attribute__((unused)), char** argv)
+{
+ char server_key[] = "../SSL/server-key.pem",
+ server_cert[] = "../SSL/server-cert.pem";
+ char ca_file[] = "../SSL/cacert.pem",
+ *ca_path = 0,
+ *cipher = 0;
+ struct st_VioSSLFd* ssl_acceptor;
+ pthread_t th;
+ TH_ARGS th_args;
+
+
+ struct sockaddr_in sa_serv;
+ struct sockaddr_in sa_cli;
+ int listen_sd;
+ int err;
+ socklen_t client_len;
+ int reuseaddr = 1; /* better testing, uh? */
+
+ MY_INIT(argv[0]);
+ DBUG_PROCESS(argv[0]);
+ DBUG_PUSH(default_dbug_option);
+
+ printf("Server key/cert : %s/%s\n", server_key, server_cert);
+ if (ca_file!=0)
+
+ printf("CAfile : %s\n", ca_file);
+ if (ca_path!=0)
+ printf("CApath : %s\n", ca_path);
+
+ th_args.ssl_acceptor = ssl_acceptor = new_VioSSLAcceptorFd(server_key, server_cert, ca_file, ca_path,cipher);
+
+ /* ----------------------------------------------- */
+ /* Prepare TCP socket for receiving connections */
+
+ listen_sd = socket (AF_INET, SOCK_STREAM, 0);
+ setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(&reuseaddr));
+
+ memset (&sa_serv, '\0', sizeof(sa_serv));
+ sa_serv.sin_family = AF_INET;
+ sa_serv.sin_addr.s_addr = INADDR_ANY;
+ sa_serv.sin_port = htons (1111); /* Server Port number */
+
+ err = bind(listen_sd, (struct sockaddr*) &sa_serv,
+ sizeof (sa_serv));
+
+ /* Receive a TCP connection. */
+
+ err = listen (listen_sd, 5);
+ client_len = sizeof(sa_cli);
+ th_args.sd = accept (listen_sd, (struct sockaddr*) &sa_cli, &client_len);
+ close (listen_sd);
+
+ printf ("Connection from %lx, port %x\n",
+ (long)sa_cli.sin_addr.s_addr, sa_cli.sin_port);
+
+ /* ----------------------------------------------- */
+ /* TCP connection is ready. Do server side SSL. */
+
+ err = pthread_create(&th, NULL, client_thread, (void*)&th_args);
+ DBUG_PRINT("info", ("pthread_create: %d", err));
+ pthread_join(th, NULL);
+
+#if 0
+ if (err<=0) {
+ my_free((uchar*)ssl_acceptor,MYF(0));
+ fatal_error("server:SSL_write");
+ }
+#endif /* 0 */
+
+ my_free((uchar*)ssl_acceptor,MYF(0));
+ return 0;
+}
+#else /* HAVE_OPENSSL */
+
+int main() {
+return 0;
+}
+#endif /* HAVE_OPENSSL */
diff --git a/externals/mysql/vio/vio.c b/externals/mysql/vio/vio.c
new file mode 100644
index 00000000000..cc5f629e26d
--- /dev/null
+++ b/externals/mysql/vio/vio.c
@@ -0,0 +1,242 @@
+/* Copyright (C) 2000 MySQL 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; version 2 of the License.
+
+ 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.
+*/
+
+#include "vio_priv.h"
+
+/*
+ * Helper to fill most of the Vio* with defaults.
+ */
+
+static void vio_init(Vio* vio, enum enum_vio_type type,
+ my_socket sd, HANDLE hPipe, uint flags)
+{
+ DBUG_ENTER("vio_init");
+ DBUG_PRINT("enter", ("type: %d sd: %d flags: %d", type, sd, flags));
+
+#ifndef HAVE_VIO_READ_BUFF
+ flags&= ~VIO_BUFFERED_READ;
+#endif
+ bzero((char*) vio, sizeof(*vio));
+ vio->type = type;
+ vio->sd = sd;
+ vio->hPipe = hPipe;
+ vio->localhost= flags & VIO_LOCALHOST;
+ if ((flags & VIO_BUFFERED_READ) &&
+ !(vio->read_buffer= (char*)my_malloc(VIO_READ_BUFFER_SIZE, MYF(MY_WME))))
+ flags&= ~VIO_BUFFERED_READ;
+#ifdef __WIN__
+ if (type == VIO_TYPE_NAMEDPIPE)
+ {
+ vio->viodelete =vio_delete;
+ vio->vioerrno =vio_errno;
+ vio->read =vio_read_pipe;
+ vio->write =vio_write_pipe;
+ vio->fastsend =vio_fastsend;
+ vio->viokeepalive =vio_keepalive;
+ vio->should_retry =vio_should_retry;
+ vio->was_interrupted=vio_was_interrupted;
+ vio->vioclose =vio_close_pipe;
+ vio->peer_addr =vio_peer_addr;
+ vio->vioblocking =vio_blocking;
+ vio->is_blocking =vio_is_blocking;
+ vio->timeout =vio_ignore_timeout;
+ }
+ else /* default is VIO_TYPE_TCPIP */
+#endif
+#ifdef HAVE_SMEM
+ if (type == VIO_TYPE_SHARED_MEMORY)
+ {
+ vio->viodelete =vio_delete;
+ vio->vioerrno =vio_errno;
+ vio->read =vio_read_shared_memory;
+ vio->write =vio_write_shared_memory;
+ vio->fastsend =vio_fastsend;
+ vio->viokeepalive =vio_keepalive;
+ vio->should_retry =vio_should_retry;
+ vio->was_interrupted=vio_was_interrupted;
+ vio->vioclose =vio_close_shared_memory;
+ vio->peer_addr =vio_peer_addr;
+ vio->vioblocking =vio_blocking;
+ vio->is_blocking =vio_is_blocking;
+ vio->timeout =vio_ignore_timeout;
+ }
+ else
+#endif
+#ifdef HAVE_OPENSSL
+ if (type == VIO_TYPE_SSL)
+ {
+ vio->viodelete =vio_ssl_delete;
+ vio->vioerrno =vio_errno;
+ vio->read =vio_ssl_read;
+ vio->write =vio_ssl_write;
+ vio->fastsend =vio_fastsend;
+ vio->viokeepalive =vio_keepalive;
+ vio->should_retry =vio_should_retry;
+ vio->was_interrupted=vio_was_interrupted;
+ vio->vioclose =vio_ssl_close;
+ vio->peer_addr =vio_peer_addr;
+ vio->vioblocking =vio_ssl_blocking;
+ vio->is_blocking =vio_is_blocking;
+ vio->timeout =vio_timeout;
+ }
+ else /* default is VIO_TYPE_TCPIP */
+#endif /* HAVE_OPENSSL */
+ {
+ vio->viodelete =vio_delete;
+ vio->vioerrno =vio_errno;
+ vio->read= (flags & VIO_BUFFERED_READ) ? vio_read_buff : vio_read;
+ vio->write =vio_write;
+ vio->fastsend =vio_fastsend;
+ vio->viokeepalive =vio_keepalive;
+ vio->should_retry =vio_should_retry;
+ vio->was_interrupted=vio_was_interrupted;
+ vio->vioclose =vio_close;
+ vio->peer_addr =vio_peer_addr;
+ vio->vioblocking =vio_blocking;
+ vio->is_blocking =vio_is_blocking;
+ vio->timeout =vio_timeout;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/* Reset initialized VIO to use with another transport type */
+
+void vio_reset(Vio* vio, enum enum_vio_type type,
+ my_socket sd, HANDLE hPipe, uint flags)
+{
+ my_free(vio->read_buffer, MYF(MY_ALLOW_ZERO_PTR));
+ vio_init(vio, type, sd, hPipe, flags);
+}
+
+
+/* Open the socket or TCP/IP connection and read the fnctl() status */
+
+Vio *vio_new(my_socket sd, enum enum_vio_type type, uint flags)
+{
+ Vio *vio;
+ DBUG_ENTER("vio_new");
+ DBUG_PRINT("enter", ("sd: %d", sd));
+ if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
+ {
+ vio_init(vio, type, sd, 0, flags);
+ sprintf(vio->desc,
+ (vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"),
+ vio->sd);
+#if !defined(__WIN__)
+#if !defined(NO_FCNTL_NONBLOCK)
+ /*
+ We call fcntl() to set the flags and then immediately read them back
+ to make sure that we and the system are in agreement on the state of
+ things.
+
+ An example of why we need to do this is FreeBSD (and apparently some
+ other BSD-derived systems, like Mac OS X), where the system sometimes
+ reports that the socket is set for non-blocking when it really will
+ block.
+ */
+ fcntl(sd, F_SETFL, 0);
+ 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);
+ vio->fcntl_mode &= ~O_NONBLOCK;
+#endif
+#else /* !defined(__WIN__) */
+ {
+ /* set to blocking mode by default */
+ ulong arg=0, r;
+ r = ioctlsocket(sd,FIONBIO,(void*) &arg);
+ vio->fcntl_mode &= ~O_NONBLOCK;
+ }
+#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_init(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, VIO_LOCALHOST);
+ strmov(vio->desc, "named pipe");
+ }
+ DBUG_RETURN(vio);
+}
+
+#ifdef HAVE_SMEM
+Vio *vio_new_win32shared_memory(NET *net,HANDLE handle_file_map, HANDLE handle_map,
+ HANDLE event_server_wrote, HANDLE event_server_read,
+ HANDLE event_client_wrote, HANDLE event_client_read,
+ HANDLE event_conn_closed)
+{
+ Vio *vio;
+ DBUG_ENTER("vio_new_win32shared_memory");
+ if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
+ {
+ vio_init(vio, VIO_TYPE_SHARED_MEMORY, 0, 0, VIO_LOCALHOST);
+ vio->handle_file_map= handle_file_map;
+ vio->handle_map= handle_map;
+ vio->event_server_wrote= event_server_wrote;
+ vio->event_server_read= event_server_read;
+ vio->event_client_wrote= event_client_wrote;
+ vio->event_client_read= event_client_read;
+ vio->event_conn_closed= event_conn_closed;
+ vio->shared_memory_remain= 0;
+ vio->shared_memory_pos= handle_map;
+ vio->net= net;
+ strmov(vio->desc, "shared memory");
+ }
+ DBUG_RETURN(vio);
+}
+#endif
+#endif
+
+
+void vio_delete(Vio* vio)
+{
+ if (!vio)
+ return; /* It must be safe to delete null pointers. */
+
+ if (vio->type != VIO_CLOSED)
+ vio->vioclose(vio);
+ my_free((uchar*) vio->read_buffer, MYF(MY_ALLOW_ZERO_PTR));
+ my_free((uchar*) vio,MYF(0));
+}
+
+
+/*
+ Cleanup memory allocated by vio or the
+ components below it when application finish
+
+*/
+void vio_end(void)
+{
+#ifdef HAVE_YASSL
+ yaSSL_CleanUp();
+#endif
+}
diff --git a/externals/mysql/vio/vio_priv.h b/externals/mysql/vio/vio_priv.h
new file mode 100644
index 00000000000..54c18dd8420
--- /dev/null
+++ b/externals/mysql/vio/vio_priv.h
@@ -0,0 +1,46 @@
+/* Copyright (C) 2003 MySQL 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; version 2 of the License.
+
+ 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 */
+
+/* Structures and functions private to the vio package */
+
+#define DONT_MAP_VIO
+#include <my_global.h>
+#include <mysql_com.h>
+#include <my_sys.h>
+#include <m_string.h>
+#include <violite.h>
+
+#ifndef __WIN__
+#include <sys/socket.h>
+#include <netdb.h>
+#endif
+
+
+void vio_ignore_timeout(Vio *vio, uint which, uint timeout);
+void vio_timeout(Vio *vio,uint which, uint timeout);
+
+#ifdef HAVE_OPENSSL
+#include "my_net.h" /* needed because of struct in_addr */
+
+size_t vio_ssl_read(Vio *vio,uchar* buf, size_t size);
+size_t vio_ssl_write(Vio *vio,const uchar* buf, size_t size);
+
+/* When the workday is over... */
+int vio_ssl_close(Vio *vio);
+void vio_ssl_delete(Vio *vio);
+
+int vio_ssl_blocking(Vio *vio, my_bool set_blocking_mode, my_bool *old_mode);
+
+#endif /* HAVE_OPENSSL */
diff --git a/externals/mysql/vio/viosocket.c b/externals/mysql/vio/viosocket.c
new file mode 100644
index 00000000000..e823f25c24e
--- /dev/null
+++ b/externals/mysql/vio/viosocket.c
@@ -0,0 +1,714 @@
+/* Copyright (C) 2000 MySQL 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; version 2 of the License.
+
+ 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.
+*/
+
+#include "vio_priv.h"
+
+int vio_errno(Vio *vio __attribute__((unused)))
+{
+ return socket_errno; /* On Win32 this mapped to WSAGetLastError() */
+}
+
+
+size_t vio_read(Vio * vio, uchar* buf, size_t size)
+{
+ size_t r;
+ DBUG_ENTER("vio_read");
+ DBUG_PRINT("enter", ("sd: %d buf: %p size: %u", vio->sd, buf,
+ (uint) size));
+
+ /* Ensure nobody uses vio_read_buff and vio_read simultaneously */
+ DBUG_ASSERT(vio->read_end == vio->read_pos);
+#ifdef __WIN__
+ r = recv(vio->sd, buf, size,0);
+#else
+ errno=0; /* For linux */
+ r = read(vio->sd, buf, size);
+#endif /* __WIN__ */
+#ifndef DBUG_OFF
+ if (r == (size_t) -1)
+ {
+ DBUG_PRINT("vio_error", ("Got error %d during read",errno));
+ }
+#endif /* DBUG_OFF */
+ DBUG_PRINT("exit", ("%ld", (long) r));
+ DBUG_RETURN(r);
+}
+
+
+/*
+ Buffered read: if average read size is small it may
+ reduce number of syscalls.
+*/
+
+size_t vio_read_buff(Vio *vio, uchar* buf, size_t size)
+{
+ size_t rc;
+#define VIO_UNBUFFERED_READ_MIN_SIZE 2048
+ DBUG_ENTER("vio_read_buff");
+ DBUG_PRINT("enter", ("sd: %d buf: %p size: %u", vio->sd, buf,
+ (uint) size));
+
+ if (vio->read_pos < vio->read_end)
+ {
+ rc= min((size_t) (vio->read_end - vio->read_pos), size);
+ memcpy(buf, vio->read_pos, rc);
+ vio->read_pos+= rc;
+ /*
+ Do not try to read from the socket now even if rc < size:
+ vio_read can return -1 due to an error or non-blocking mode, and
+ the safest way to handle it is to move to a separate branch.
+ */
+ }
+ else if (size < VIO_UNBUFFERED_READ_MIN_SIZE)
+ {
+ rc= vio_read(vio, (uchar*) vio->read_buffer, VIO_READ_BUFFER_SIZE);
+ if (rc != 0 && rc != (size_t) -1)
+ {
+ if (rc > size)
+ {
+ vio->read_pos= vio->read_buffer + size;
+ vio->read_end= vio->read_buffer + rc;
+ rc= size;
+ }
+ memcpy(buf, vio->read_buffer, rc);
+ }
+ }
+ else
+ rc= vio_read(vio, buf, size);
+ DBUG_RETURN(rc);
+#undef VIO_UNBUFFERED_READ_MIN_SIZE
+}
+
+
+size_t vio_write(Vio * vio, const uchar* buf, size_t size)
+{
+ size_t r;
+ DBUG_ENTER("vio_write");
+ DBUG_PRINT("enter", ("sd: %d buf: %p size: %u", vio->sd, buf,
+ (uint) size));
+#ifdef __WIN__
+ r = send(vio->sd, buf, size,0);
+#else
+ r = write(vio->sd, buf, size);
+#endif /* __WIN__ */
+#ifndef DBUG_OFF
+ if (r == (size_t) -1)
+ {
+ DBUG_PRINT("vio_error", ("Got error on write: %d",socket_errno));
+ }
+#endif /* DBUG_OFF */
+ DBUG_PRINT("exit", ("%u", (uint) r));
+ DBUG_RETURN(r);
+}
+
+int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode,
+ my_bool *old_mode)
+{
+ int r=0;
+ DBUG_ENTER("vio_blocking");
+
+ *old_mode= test(!(vio->fcntl_mode & O_NONBLOCK));
+ DBUG_PRINT("enter", ("set_blocking_mode: %d old_mode: %d",
+ (int) set_blocking_mode, (int) *old_mode));
+
+#if !defined(__WIN__)
+#if !defined(NO_FCNTL_NONBLOCK)
+ if (vio->sd >= 0)
+ {
+ int old_fcntl=vio->fcntl_mode;
+ if (set_blocking_mode)
+ vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
+ else
+ vio->fcntl_mode |= O_NONBLOCK; /* set bit */
+ if (old_fcntl != vio->fcntl_mode)
+ {
+ r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
+ if (r == -1)
+ {
+ DBUG_PRINT("info", ("fcntl failed, errno %d", errno));
+ vio->fcntl_mode= old_fcntl;
+ }
+ }
+ }
+#else
+ r= set_blocking_mode ? 0 : 1;
+#endif /* !defined(NO_FCNTL_NONBLOCK) */
+#else /* !defined(__WIN__) */
+ if (vio->type != VIO_TYPE_NAMEDPIPE && vio->type != VIO_TYPE_SHARED_MEMORY)
+ {
+ ulong arg;
+ int old_fcntl=vio->fcntl_mode;
+ if (set_blocking_mode)
+ {
+ arg = 0;
+ vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
+ }
+ else
+ {
+ arg = 1;
+ vio->fcntl_mode |= O_NONBLOCK; /* set bit */
+ }
+ if (old_fcntl != vio->fcntl_mode)
+ r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg);
+ }
+ else
+ r= test(!(vio->fcntl_mode & O_NONBLOCK)) != set_blocking_mode;
+#endif /* !defined(__WIN__) */
+ DBUG_PRINT("exit", ("%d", r));
+ DBUG_RETURN(r);
+}
+
+my_bool
+vio_is_blocking(Vio * vio)
+{
+ my_bool r;
+ DBUG_ENTER("vio_is_blocking");
+ r = !(vio->fcntl_mode & O_NONBLOCK);
+ DBUG_PRINT("exit", ("%d", (int) r));
+ DBUG_RETURN(r);
+}
+
+
+int vio_fastsend(Vio * vio __attribute__((unused)))
+{
+ int r=0;
+ DBUG_ENTER("vio_fastsend");
+
+#if defined(IPTOS_THROUGHPUT)
+ {
+ int tos = IPTOS_THROUGHPUT;
+ r= setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos));
+ }
+#endif /* IPTOS_THROUGHPUT */
+ if (!r)
+ {
+#ifdef __WIN__
+ BOOL nodelay= 1;
+#else
+ int nodelay = 1;
+#endif
+
+ r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY,
+ IF_WIN(const char*, void*) &nodelay,
+ sizeof(nodelay));
+
+ }
+ if (r)
+ {
+ DBUG_PRINT("warning", ("Couldn't set socket option for fast send"));
+ r= -1;
+ }
+ DBUG_PRINT("exit", ("%d", r));
+ DBUG_RETURN(r);
+}
+
+int vio_keepalive(Vio* vio, my_bool set_keep_alive)
+{
+ int r=0;
+ uint opt = 0;
+ DBUG_ENTER("vio_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_should_retry(Vio * vio __attribute__((unused)))
+{
+ int en = socket_errno;
+ return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
+ en == SOCKET_EWOULDBLOCK);
+}
+
+
+my_bool
+vio_was_interrupted(Vio *vio __attribute__((unused)))
+{
+ int en= socket_errno;
+ return (en == SOCKET_EAGAIN || en == SOCKET_EINTR ||
+ en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT);
+}
+
+
+int vio_close(Vio * vio)
+{
+ int r=0;
+ DBUG_ENTER("vio_close");
+#ifdef _WIN32
+ if (vio->type == VIO_TYPE_NAMEDPIPE)
+ {
+#ifdef MYSQL_SERVER
+ CancelIo(vio->hPipe);
+ DisconnectNamedPipe(vio->hPipe);
+#endif
+ r=CloseHandle(vio->hPipe);
+ }
+ else
+#endif /* _WIN32 */
+ if (vio->type != VIO_CLOSED)
+ {
+ DBUG_ASSERT(vio->sd >= 0);
+ if (shutdown(vio->sd, SHUT_RDWR))
+ r= -1;
+ if (closesocket(vio->sd))
+ r= -1;
+ }
+ if (r)
+ {
+ DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno));
+ /* FIXME: error handling (not critical for MySQL) */
+ }
+ vio->type= VIO_CLOSED;
+ vio->sd= -1;
+ DBUG_RETURN(r);
+}
+
+
+const char *vio_description(Vio * vio)
+{
+ return vio->desc;
+}
+
+enum enum_vio_type vio_type(Vio* vio)
+{
+ return vio->type;
+}
+
+my_socket vio_fd(Vio* vio)
+{
+ return vio->sd;
+}
+
+my_bool vio_peer_addr(Vio *vio, char *buf, uint16 *port, size_t buflen)
+{
+ DBUG_ENTER("vio_peer_addr");
+ DBUG_PRINT("enter", ("sd: %d", vio->sd));
+
+ if (vio->localhost)
+ {
+ strmov(buf, "127.0.0.1");
+ *port= 0;
+ }
+ else
+ {
+ int error;
+ char port_buf[NI_MAXSERV];
+ socklen_t addrLen = sizeof(vio->remote);
+ if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote),
+ &addrLen) != 0)
+ {
+ DBUG_PRINT("exit", ("getpeername gave error: %d", socket_errno));
+ DBUG_RETURN(1);
+ }
+ vio->addrLen= (int)addrLen;
+
+ if ((error= getnameinfo((struct sockaddr *)(&vio->remote),
+ addrLen,
+ buf, buflen,
+ port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV)))
+ {
+ DBUG_PRINT("exit", ("getnameinfo gave error: %s",
+ gai_strerror(error)));
+ DBUG_RETURN(1);
+ }
+
+ *port= (uint16)strtol(port_buf, (char **)NULL, 10);
+
+ /*
+ A lot of users do not have IPv6 loopback resolving to localhost
+ correctly setup. Should this exist? No. If we do not do it though
+ we will be getting a lot of support questions from users who
+ have bad setups. This code should be removed by say... 2012.
+ -Brian
+ */
+ if (!memcmp(buf, "::ffff:127.0.0.1", sizeof("::ffff:127.0.0.1")))
+ strmov(buf, "127.0.0.1");
+ }
+ DBUG_PRINT("exit", ("addr: %s", buf));
+ DBUG_RETURN(0);
+}
+
+
+/* Return 0 if there is data to be read */
+
+my_bool vio_poll_read(Vio *vio,uint timeout)
+{
+#ifdef __WIN__
+ int res;
+ my_socket fd= vio->sd;
+ fd_set readfds, errorfds;
+ struct timeval tm;
+ DBUG_ENTER("vio_poll");
+ tm.tv_sec= timeout;
+ tm.tv_usec= 0;
+ FD_ZERO(&readfds);
+ FD_ZERO(&errorfds);
+ FD_SET(fd, &readfds);
+ FD_SET(fd, &errorfds);
+ /* The first argument is ignored on Windows, so a conversion to int is OK */
+ if ((res= select((int) fd, &readfds, NULL, &errorfds, &tm) <= 0))
+ {
+ DBUG_RETURN(res < 0 ? 0 : 1);
+ }
+ res= FD_ISSET(fd, &readfds) || FD_ISSET(fd, &errorfds);
+ DBUG_RETURN(!res);
+#elif defined(HAVE_POLL)
+ struct pollfd fds;
+ int res;
+ DBUG_ENTER("vio_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 | POLLERR | POLLHUP) ? 0 : 1);
+#else
+ return 0;
+#endif
+}
+
+
+my_bool vio_peek_read(Vio *vio, uint *bytes)
+{
+#ifdef __WIN__
+ int len;
+ if (ioctlsocket(vio->sd, FIONREAD, &len))
+ return TRUE;
+ *bytes= len;
+ return FALSE;
+#elif FIONREAD_IN_SYS_IOCTL
+ int len;
+ if (ioctl(vio->sd, FIONREAD, &len) < 0)
+ return TRUE;
+ *bytes= len;
+ return FALSE;
+#else
+ char buf[1024];
+ ssize_t res= recv(vio->sd, &buf, sizeof(buf), MSG_PEEK);
+ if (res < 0)
+ return TRUE;
+ *bytes= res;
+ return FALSE;
+#endif
+}
+
+void vio_timeout(Vio *vio, uint which, uint timeout)
+{
+#if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)
+ int r;
+ DBUG_ENTER("vio_timeout");
+
+ {
+#ifdef __WIN__
+ /* Windows expects time in milliseconds as int */
+ int wait_timeout= (int) timeout * 1000;
+#else
+ /* POSIX specifies time as struct timeval. */
+ struct timeval wait_timeout;
+ wait_timeout.tv_sec= timeout;
+ wait_timeout.tv_usec= 0;
+#endif
+
+ r= setsockopt(vio->sd, SOL_SOCKET, which ? SO_SNDTIMEO : SO_RCVTIMEO,
+ IF_WIN(const char*, const void*)&wait_timeout,
+ sizeof(wait_timeout));
+
+ }
+
+#ifndef DBUG_OFF
+ if (r != 0)
+ DBUG_PRINT("error", ("setsockopt failed: %d, errno: %d", r, socket_errno));
+#endif
+
+ DBUG_VOID_RETURN;
+#else
+/*
+ Platforms not suporting setting of socket timeout should either use
+ thr_alarm or just run without read/write timeout(s)
+*/
+#endif
+}
+
+
+#ifdef __WIN__
+size_t vio_read_pipe(Vio * vio, uchar* buf, size_t size)
+{
+ DWORD length;
+ DBUG_ENTER("vio_read_pipe");
+ DBUG_PRINT("enter", ("sd: %d buf: %p size: %u", vio->sd, buf,
+ (uint) size));
+
+ if (!ReadFile(vio->hPipe, buf, size, &length, NULL))
+ DBUG_RETURN(-1);
+
+ DBUG_PRINT("exit", ("%d", length));
+ DBUG_RETURN((size_t) length);
+}
+
+
+size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size)
+{
+ DWORD length;
+ DBUG_ENTER("vio_write_pipe");
+ DBUG_PRINT("enter", ("sd: %d buf: %p size: %u", vio->sd, buf,
+ (uint) size));
+
+ if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL))
+ DBUG_RETURN(-1);
+
+ DBUG_PRINT("exit", ("%d", length));
+ DBUG_RETURN((size_t) length);
+}
+
+int vio_close_pipe(Vio * vio)
+{
+ int r;
+ DBUG_ENTER("vio_close_pipe");
+#ifdef MYSQL_SERVER
+ CancelIo(vio->hPipe);
+ DisconnectNamedPipe(vio->hPipe);
+#endif
+ r=CloseHandle(vio->hPipe);
+ if (r)
+ {
+ DBUG_PRINT("vio_error", ("close() failed, error: %d",GetLastError()));
+ /* FIXME: error handling (not critical for MySQL) */
+ }
+ vio->type= VIO_CLOSED;
+ vio->sd= -1;
+ DBUG_RETURN(r);
+}
+
+
+void vio_ignore_timeout(Vio *vio __attribute__((unused)),
+ uint which __attribute__((unused)),
+ uint timeout __attribute__((unused)))
+{
+}
+
+
+#ifdef HAVE_SMEM
+
+size_t vio_read_shared_memory(Vio * vio, uchar* buf, size_t size)
+{
+ size_t length;
+ size_t remain_local;
+ char *current_postion;
+ HANDLE events[2];
+
+ DBUG_ENTER("vio_read_shared_memory");
+ DBUG_PRINT("enter", ("sd: %d buf: %p size: %d", vio->sd, buf,
+ size));
+
+ remain_local = size;
+ current_postion=buf;
+
+ events[0]= vio->event_server_wrote;
+ events[1]= vio->event_conn_closed;
+
+ do
+ {
+ if (vio->shared_memory_remain == 0)
+ {
+ /*
+ WaitForMultipleObjects can return next values:
+ WAIT_OBJECT_0+0 - event from vio->event_server_wrote
+ WAIT_OBJECT_0+1 - event from vio->event_conn_closed. We can't read
+ anything
+ WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail. We can't read anything
+ */
+ if (WaitForMultipleObjects(array_elements(events), events, FALSE,
+ vio->net->read_timeout*1000) != WAIT_OBJECT_0)
+ {
+ DBUG_RETURN(-1);
+ };
+
+ vio->shared_memory_pos = vio->handle_map;
+ vio->shared_memory_remain = uint4korr((ulong*)vio->shared_memory_pos);
+ vio->shared_memory_pos+=4;
+ }
+
+ length = size;
+
+ if (vio->shared_memory_remain < length)
+ length = vio->shared_memory_remain;
+ if (length > remain_local)
+ length = remain_local;
+
+ memcpy(current_postion,vio->shared_memory_pos,length);
+
+ vio->shared_memory_remain-=length;
+ vio->shared_memory_pos+=length;
+ current_postion+=length;
+ remain_local-=length;
+
+ if (!vio->shared_memory_remain)
+ {
+ if (!SetEvent(vio->event_client_read))
+ DBUG_RETURN(-1);
+ }
+ } while (remain_local);
+ length = size;
+
+ DBUG_PRINT("exit", ("%lu", (ulong) length));
+ DBUG_RETURN(length);
+}
+
+
+size_t vio_write_shared_memory(Vio * vio, const uchar* buf, size_t size)
+{
+ size_t length, remain, sz;
+ HANDLE pos;
+ const uchar *current_postion;
+ HANDLE events[2];
+
+ DBUG_ENTER("vio_write_shared_memory");
+ DBUG_PRINT("enter", ("sd: %d buf: %p size: %d", vio->sd, buf,
+ size));
+
+ remain = size;
+ current_postion = buf;
+
+ events[0]= vio->event_server_read;
+ events[1]= vio->event_conn_closed;
+
+ while (remain != 0)
+ {
+ if (WaitForMultipleObjects(array_elements(events), events, FALSE,
+ vio->net->write_timeout*1000) != WAIT_OBJECT_0)
+ {
+ DBUG_RETURN((size_t) -1);
+ }
+
+ sz= (remain > shared_memory_buffer_length ? shared_memory_buffer_length :
+ remain);
+
+ int4store(vio->handle_map,sz);
+ pos = vio->handle_map + 4;
+ memcpy(pos,current_postion,sz);
+ remain-=sz;
+ current_postion+=sz;
+ if (!SetEvent(vio->event_client_wrote))
+ DBUG_RETURN((size_t) -1);
+ }
+ length = size;
+
+ DBUG_PRINT("exit", ("%lu", (ulong) length));
+ DBUG_RETURN(length);
+}
+
+
+/**
+ Close shared memory and DBUG_PRINT any errors that happen on closing.
+ @return Zero if all closing functions succeed, and nonzero otherwise.
+*/
+int vio_close_shared_memory(Vio * vio)
+{
+ int error_count= 0;
+ DBUG_ENTER("vio_close_shared_memory");
+ if (vio->type != VIO_CLOSED)
+ {
+ /*
+ Set event_conn_closed for notification of both client and server that
+ connection is closed
+ */
+ SetEvent(vio->event_conn_closed);
+ /*
+ Close all handlers. UnmapViewOfFile and CloseHandle return non-zero
+ result if they are success.
+ */
+ if (UnmapViewOfFile(vio->handle_map) == 0)
+ {
+ error_count++;
+ DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed"));
+ }
+ if (CloseHandle(vio->event_server_wrote) == 0)
+ {
+ error_count++;
+ DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed"));
+ }
+ if (CloseHandle(vio->event_server_read) == 0)
+ {
+ error_count++;
+ DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed"));
+ }
+ if (CloseHandle(vio->event_client_wrote) == 0)
+ {
+ error_count++;
+ DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed"));
+ }
+ if (CloseHandle(vio->event_client_read) == 0)
+ {
+ error_count++;
+ DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed"));
+ }
+ if (CloseHandle(vio->handle_file_map) == 0)
+ {
+ error_count++;
+ DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed"));
+ }
+ if (CloseHandle(vio->event_conn_closed) == 0)
+ {
+ error_count++;
+ DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed"));
+ }
+ }
+ vio->type= VIO_CLOSED;
+ vio->sd= -1;
+ DBUG_RETURN(error_count);
+}
+#endif /* HAVE_SMEM */
+#endif /* __WIN__ */
+
+
+/**
+ Number of bytes in the read buffer.
+
+ @return number of bytes in the read buffer or < 0 if error.
+*/
+
+ssize_t vio_pending(Vio *vio)
+{
+#ifdef HAVE_OPENSSL
+ SSL *ssl= (SSL*) vio->ssl_arg;
+#endif
+
+ if (vio->read_pos < vio->read_end)
+ return vio->read_end - vio->read_pos;
+
+#ifdef HAVE_OPENSSL
+ if (ssl)
+ return SSL_pending(ssl);
+#endif
+
+ return 0;
+}
diff --git a/externals/mysql/vio/viossl.c b/externals/mysql/vio/viossl.c
new file mode 100644
index 00000000000..9cbd74034a9
--- /dev/null
+++ b/externals/mysql/vio/viossl.c
@@ -0,0 +1,279 @@
+/* Copyright (C) 2000 MySQL 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; version 2 of the License.
+
+ 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.
+*/
+
+#include "vio_priv.h"
+
+#ifdef HAVE_OPENSSL
+
+#ifdef __NETWARE__
+
+/* yaSSL already uses BSD sockets */
+#ifndef HAVE_YASSL
+
+/*
+ The default OpenSSL implementation on NetWare uses WinSock.
+ This code allows us to use the BSD sockets.
+*/
+
+static int SSL_set_fd_bsd(SSL *s, int fd)
+{
+ int result= -1;
+ BIO_METHOD *BIO_s_bsdsocket();
+ BIO *bio;
+
+ if ((bio= BIO_new(BIO_s_bsdsocket())))
+ {
+ result= BIO_set_fd(bio, fd, BIO_NOCLOSE);
+ SSL_set_bio(s, bio, bio);
+ }
+ return result;
+}
+
+#define SSL_set_fd(A, B) SSL_set_fd_bsd((A), (B))
+
+#endif /* HAVE_YASSL */
+#endif /* __NETWARE__ */
+
+
+static void
+report_errors(SSL* ssl)
+{
+ unsigned long l;
+ const char *file;
+ const char *data;
+ int line, flags;
+#ifndef DBUG_OFF
+ char buf[512];
+#endif
+
+ DBUG_ENTER("report_errors");
+
+ while ((l= ERR_get_error_line_data(&file,&line,&data,&flags)))
+ {
+ DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
+ file,line,(flags&ERR_TXT_STRING)?data:"")) ;
+ }
+
+ if (ssl)
+ DBUG_PRINT("error", ("error: %s",
+ ERR_error_string(SSL_get_error(ssl, l), buf)));
+
+ DBUG_PRINT("info", ("socket_errno: %d", socket_errno));
+ DBUG_VOID_RETURN;
+}
+
+
+size_t vio_ssl_read(Vio *vio, uchar* buf, size_t size)
+{
+ size_t r;
+ DBUG_ENTER("vio_ssl_read");
+ DBUG_PRINT("enter", ("sd: %d buf: %p size: %u ssl: %p",
+ vio->sd, buf, (uint) size, vio->ssl_arg));
+
+ r= SSL_read((SSL*) vio->ssl_arg, buf, size);
+#ifndef DBUG_OFF
+ if (r == (size_t) -1)
+ report_errors((SSL*) vio->ssl_arg);
+#endif
+ DBUG_PRINT("exit", ("%u", (uint) r));
+ DBUG_RETURN(r);
+}
+
+
+size_t vio_ssl_write(Vio *vio, const uchar* buf, size_t size)
+{
+ size_t r;
+ DBUG_ENTER("vio_ssl_write");
+ DBUG_PRINT("enter", ("sd: %d buf: %p size: %u", vio->sd,
+ buf, (uint) size));
+
+ r= SSL_write((SSL*) vio->ssl_arg, buf, size);
+#ifndef DBUG_OFF
+ if (r == (size_t) -1)
+ report_errors((SSL*) vio->ssl_arg);
+#endif
+ DBUG_PRINT("exit", ("%u", (uint) r));
+ DBUG_RETURN(r);
+}
+
+
+int vio_ssl_close(Vio *vio)
+{
+ int r= 0;
+ SSL *ssl= (SSL*)vio->ssl_arg;
+ DBUG_ENTER("vio_ssl_close");
+
+ if (ssl)
+ {
+ /*
+ THE SSL standard says that SSL sockets must send and receive a close_notify
+ alert on socket shutdown to avoid truncation attacks. However, this can
+ cause problems since we often hold a lock during shutdown and this IO can
+ take an unbounded amount of time to complete. Since our packets are self
+ describing with length, we aren't vunerable to these attacks. Therefore,
+ we just shutdown by closing the socket (quiet shutdown).
+ */
+ SSL_set_quiet_shutdown(ssl, 1);
+
+ switch ((r= SSL_shutdown(ssl))) {
+ case 1:
+ /* Shutdown successful */
+ break;
+ case 0:
+ /*
+ Shutdown not yet finished - since the socket is going to
+ be closed there is no need to call SSL_shutdown() a second
+ time to wait for the other side to respond
+ */
+ break;
+ default: /* Shutdown failed */
+ DBUG_PRINT("vio_error", ("SSL_shutdown() failed, error: %d",
+ SSL_get_error(ssl, r)));
+ break;
+ }
+ }
+ DBUG_RETURN(vio_close(vio));
+}
+
+
+void vio_ssl_delete(Vio *vio)
+{
+ if (!vio)
+ return; /* It must be safe to delete null pointer */
+
+ if (vio->type == VIO_TYPE_SSL)
+ vio_ssl_close(vio); /* Still open, close connection first */
+
+ if (vio->ssl_arg)
+ {
+ SSL_free((SSL*) vio->ssl_arg);
+ vio->ssl_arg= 0;
+ }
+
+ vio_delete(vio);
+}
+
+#ifndef EMBEDDED_LIBRARY
+static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout,
+ int (*connect_accept_func)(SSL*))
+{
+ SSL *ssl;
+ my_bool unused;
+ my_bool was_blocking;
+
+ DBUG_ENTER("ssl_do");
+ DBUG_PRINT("enter", ("ptr: %p, sd: %d ctx: %p",
+ ptr, vio->sd, ptr->ssl_context));
+
+ /* Set socket to blocking if not already set */
+ vio_blocking(vio, 1, &was_blocking);
+
+ if (!(ssl= SSL_new(ptr->ssl_context)))
+ {
+ DBUG_PRINT("error", ("SSL_new failure"));
+ report_errors(ssl);
+ vio_blocking(vio, was_blocking, &unused);
+ DBUG_RETURN(1);
+ }
+ DBUG_PRINT("info", ("ssl: %p timeout: %ld", ssl, timeout));
+ SSL_clear(ssl);
+ SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout);
+ SSL_set_fd(ssl, vio->sd);
+
+ if (connect_accept_func(ssl) < 1)
+ {
+ DBUG_PRINT("error", ("SSL_connect/accept failure"));
+ report_errors(ssl);
+ SSL_free(ssl);
+ vio_blocking(vio, was_blocking, &unused);
+ DBUG_RETURN(1);
+ }
+
+ /*
+ Connection succeeded. Install new function handlers,
+ change type, set sd to the fd used when connecting
+ and set pointer to the SSL structure
+ */
+ vio_reset(vio, VIO_TYPE_SSL, SSL_get_fd(ssl), 0, 0);
+ vio->ssl_arg= (void*)ssl;
+
+#ifndef DBUG_OFF
+ {
+ /* Print some info about the peer */
+ X509 *cert;
+ char buf[512];
+
+ DBUG_PRINT("info",("SSL connection succeeded"));
+ DBUG_PRINT("info",("Using cipher: '%s'" , SSL_get_cipher_name(ssl)));
+
+ if ((cert= SSL_get_peer_certificate (ssl)))
+ {
+ DBUG_PRINT("info",("Peer certificate:"));
+ X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
+ DBUG_PRINT("info",("\t subject: '%s'", buf));
+ X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
+ DBUG_PRINT("info",("\t issuer: '%s'", buf));
+ X509_free(cert);
+ }
+ else
+ DBUG_PRINT("info",("Peer does not have certificate."));
+
+ if (SSL_get_shared_ciphers(ssl, buf, sizeof(buf)))
+ {
+ DBUG_PRINT("info",("shared_ciphers: '%s'", buf));
+ }
+ else
+ DBUG_PRINT("info",("no shared ciphers!"));
+ }
+#endif
+
+ DBUG_RETURN(0);
+}
+
+
+int sslaccept(struct st_VioSSLFd *ptr, Vio *vio, long timeout)
+{
+ DBUG_ENTER("sslaccept");
+ DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_accept));
+}
+
+
+int sslconnect(struct st_VioSSLFd *ptr, Vio *vio, long timeout)
+{
+ DBUG_ENTER("sslconnect");
+ DBUG_RETURN(ssl_do(ptr, vio, timeout, SSL_connect));
+}
+#endif /*EMBEDDED_LIBRARY*/
+
+int vio_ssl_blocking(Vio *vio __attribute__((unused)),
+ my_bool set_blocking_mode,
+ my_bool *old_mode)
+{
+ /* Mode is always blocking */
+ *old_mode= 1;
+ /* Return error if we try to change to non_blocking mode */
+ return (set_blocking_mode ? 0 : 1);
+}
+
+
+
+#endif /* HAVE_OPENSSL */
diff --git a/externals/mysql/vio/viosslfactories.c b/externals/mysql/vio/viosslfactories.c
new file mode 100644
index 00000000000..95dbd73d24d
--- /dev/null
+++ b/externals/mysql/vio/viosslfactories.c
@@ -0,0 +1,385 @@
+/* Copyright (C) 2000 MySQL 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; version 2 of the License.
+
+ 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 */
+
+#include "vio_priv.h"
+
+#ifdef HAVE_OPENSSL
+
+static my_bool ssl_algorithms_added = FALSE;
+static my_bool ssl_error_strings_loaded= FALSE;
+static int verify_depth = 0;
+
+static unsigned char dh512_p[]=
+{
+ 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75,
+ 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F,
+ 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3,
+ 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12,
+ 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C,
+ 0x47,0x74,0xE8,0x33,
+};
+
+static unsigned char dh512_g[]={
+ 0x02,
+};
+
+static DH *get_dh512(void)
+{
+ DH *dh;
+ if ((dh=DH_new()))
+ {
+ dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL);
+ dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL);
+ if (! dh->p || ! dh->g)
+ {
+ DH_free(dh);
+ dh=0;
+ }
+ }
+ return(dh);
+}
+
+
+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)
+ {
+#ifndef DBUG_OFF /* Avoid warning */
+ char buf[200];
+ DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%s\n", ERR_error_string(l,buf),
+ file,line,(flags & ERR_TXT_STRING) ? data : "")) ;
+#endif
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+static int
+vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file)
+{
+ DBUG_ENTER("vio_set_cert_stuff");
+ DBUG_PRINT("enter", ("ctx: %p cert_file: %s key_file: %s",
+ ctx, cert_file, key_file));
+ if (cert_file)
+ {
+ if (SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0)
+ {
+ DBUG_PRINT("error",("unable to get certificate from '%s'", cert_file));
+ DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE););
+ fprintf(stderr, "SSL error: Unable to get certificate from '%s'\n",
+ cert_file);
+ fflush(stderr);
+ DBUG_RETURN(1);
+ }
+
+ if (!key_file)
+ key_file= cert_file;
+
+ if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0)
+ {
+ DBUG_PRINT("error", ("unable to get private key from '%s'", key_file));
+ DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE););
+ fprintf(stderr, "SSL error: Unable to get private key from '%s'\n",
+ key_file);
+ fflush(stderr);
+ DBUG_RETURN(1);
+ }
+
+ /*
+ If we are using DSA, we can copy the parameters from the private key
+ Now we know that a key and cert have been set against the SSL context
+ */
+ if (!SSL_CTX_check_private_key(ctx))
+ {
+ DBUG_PRINT("error",
+ ("Private key does not match the certificate public key"));
+ DBUG_EXECUTE("error", ERR_print_errors_fp(DBUG_FILE););
+ fprintf(stderr,
+ "SSL error: "
+ "Private key does not match the certificate public key\n");
+ fflush(stderr);
+ DBUG_RETURN(1);
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+
+static int
+vio_verify_callback(int ok, X509_STORE_CTX *ctx)
+{
+ char buf[256];
+ X509 *err_cert;
+
+ DBUG_ENTER("vio_verify_callback");
+ DBUG_PRINT("enter", ("ok: %d ctx: %p", ok, ctx));
+
+ err_cert= X509_STORE_CTX_get_current_cert(ctx);
+ X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
+ DBUG_PRINT("info", ("cert: %s", buf));
+ if (!ok)
+ {
+ int err, depth;
+ err= X509_STORE_CTX_get_error(ctx);
+ depth= X509_STORE_CTX_get_error_depth(ctx);
+
+ DBUG_PRINT("error",("verify error: %d '%s'",err,
+ X509_verify_cert_error_string(err)));
+ /*
+ Approve cert if depth is greater then "verify_depth", currently
+ verify_depth is always 0 and there is no way to increase it.
+ */
+ if (verify_depth >= depth)
+ ok= 1;
+ }
+ 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", ("%d", ok));
+ DBUG_RETURN(ok);
+}
+
+
+#ifdef __NETWARE__
+
+/* NetWare SSL cleanup */
+void netware_ssl_cleanup()
+{
+ /* free memory from SSL_library_init() */
+ EVP_cleanup();
+
+/* OpenSSL NetWare port specific functions */
+#ifndef HAVE_YASSL
+
+ /* free global X509 method */
+ X509_STORE_method_cleanup();
+
+ /* free the thread_hash error table */
+ ERR_free_state_table();
+#endif
+}
+
+
+/* NetWare SSL initialization */
+static void netware_ssl_init()
+{
+ /* cleanup OpenSSL library */
+ NXVmRegisterExitHandler(netware_ssl_cleanup, NULL);
+}
+
+#endif /* __NETWARE__ */
+
+
+static void check_ssl_init()
+{
+ if (!ssl_algorithms_added)
+ {
+ ssl_algorithms_added= TRUE;
+ SSL_library_init();
+ OpenSSL_add_all_algorithms();
+
+ }
+
+#ifdef __NETWARE__
+ netware_ssl_init();
+#endif
+
+ if (!ssl_error_strings_loaded)
+ {
+ ssl_error_strings_loaded= TRUE;
+ SSL_load_error_strings();
+ }
+}
+
+#ifndef EMBEDDED_LIBRARY
+/************************ VioSSLFd **********************************/
+static struct st_VioSSLFd *
+new_VioSSLFd(const char *key_file, const char *cert_file,
+ const char *ca_file, const char *ca_path,
+ const char *cipher, SSL_METHOD *method)
+{
+ DH *dh;
+ struct st_VioSSLFd *ssl_fd;
+ DBUG_ENTER("new_VioSSLFd");
+ DBUG_PRINT("enter",
+ ("key_file: '%s' cert_file: '%s' ca_file: '%s' ca_path: '%s' "
+ "cipher: '%s'",
+ key_file ? key_file : "NULL",
+ cert_file ? cert_file : "NULL",
+ ca_file ? ca_file : "NULL",
+ ca_path ? ca_path : "NULL",
+ cipher ? cipher : "NULL"));
+
+ check_ssl_init();
+
+ if (!(ssl_fd= ((struct st_VioSSLFd*)
+ my_malloc(sizeof(struct st_VioSSLFd),MYF(0)))))
+ DBUG_RETURN(0);
+
+ if (!(ssl_fd->ssl_context= SSL_CTX_new(method)))
+ {
+ DBUG_PRINT("error", ("SSL_CTX_new failed"));
+ report_errors();
+ my_free((void*)ssl_fd,MYF(0));
+ DBUG_RETURN(0);
+ }
+
+ /*
+ Set the ciphers that can be used
+ NOTE: SSL_CTX_set_cipher_list will return 0 if
+ none of the provided ciphers could be selected
+ */
+ if (cipher &&
+ SSL_CTX_set_cipher_list(ssl_fd->ssl_context, cipher) == 0)
+ {
+ DBUG_PRINT("error", ("failed to set ciphers to use"));
+ report_errors();
+ SSL_CTX_free(ssl_fd->ssl_context);
+ my_free((void*)ssl_fd,MYF(0));
+ DBUG_RETURN(0);
+ }
+
+ /* Load certs from the trusted ca */
+ if (SSL_CTX_load_verify_locations(ssl_fd->ssl_context, ca_file, ca_path) == 0)
+ {
+ DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
+ if (SSL_CTX_set_default_verify_paths(ssl_fd->ssl_context) == 0)
+ {
+ DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed"));
+ report_errors();
+ SSL_CTX_free(ssl_fd->ssl_context);
+ my_free((void*)ssl_fd,MYF(0));
+ DBUG_RETURN(0);
+ }
+ }
+
+ if (vio_set_cert_stuff(ssl_fd->ssl_context, cert_file, key_file))
+ {
+ DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
+ report_errors();
+ SSL_CTX_free(ssl_fd->ssl_context);
+ my_free((void*)ssl_fd,MYF(0));
+ DBUG_RETURN(0);
+ }
+
+ /* DH stuff */
+ dh=get_dh512();
+ SSL_CTX_set_tmp_dh(ssl_fd->ssl_context, dh);
+ DH_free(dh);
+
+ DBUG_PRINT("exit", ("OK 1"));
+
+ DBUG_RETURN(ssl_fd);
+}
+
+
+/************************ VioSSLConnectorFd **********************************/
+struct st_VioSSLFd *
+new_VioSSLConnectorFd(const char *key_file, const char *cert_file,
+ const char *ca_file, const char *ca_path,
+ const char *cipher)
+{
+ struct st_VioSSLFd *ssl_fd;
+ int verify= SSL_VERIFY_PEER;
+
+ /*
+ Turn off verification of servers certificate if both
+ ca_file and ca_path is set to NULL
+ */
+ if (ca_file == 0 && ca_path == 0)
+ verify= SSL_VERIFY_NONE;
+
+ if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file,
+ ca_path, cipher, TLSv1_client_method())))
+ {
+ return 0;
+ }
+
+ /* Init the VioSSLFd as a "connector" ie. the client side */
+
+ /*
+ The verify_callback function is used to control the behaviour
+ when the SSL_VERIFY_PEER flag is set.
+ */
+ SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback);
+
+ return ssl_fd;
+}
+
+
+/************************ VioSSLAcceptorFd **********************************/
+struct st_VioSSLFd *
+new_VioSSLAcceptorFd(const char *key_file, const char *cert_file,
+ const char *ca_file, const char *ca_path,
+ const char *cipher)
+{
+ struct st_VioSSLFd *ssl_fd;
+ int verify= SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE;
+ if (!(ssl_fd= new_VioSSLFd(key_file, cert_file, ca_file,
+ ca_path, cipher, TLSv1_server_method())))
+ {
+ return 0;
+ }
+ /* Init the the VioSSLFd as a "acceptor" ie. the server side */
+
+ /* Set max number of cached sessions, returns the previous size */
+ SSL_CTX_sess_set_cache_size(ssl_fd->ssl_context, 128);
+
+ /*
+ The verify_callback function is used to control the behaviour
+ when the SSL_VERIFY_PEER flag is set.
+ */
+ SSL_CTX_set_verify(ssl_fd->ssl_context, verify, vio_verify_callback);
+
+ /*
+ Set session_id - an identifier for this server session
+ Use the ssl_fd pointer
+ */
+ SSL_CTX_set_session_id_context(ssl_fd->ssl_context,
+ (const unsigned char *)ssl_fd,
+ sizeof(ssl_fd));
+
+ return ssl_fd;
+}
+
+void free_vio_ssl_acceptor_fd(struct st_VioSSLFd *fd)
+{
+ SSL_CTX_free(fd->ssl_context);
+ my_free((uchar*) fd, MYF(0));
+}
+#endif /*EMBEDDED_LIBRARY*/
+#endif /* HAVE_OPENSSL */
diff --git a/externals/mysql/vio/viotest-ssl.c b/externals/mysql/vio/viotest-ssl.c
new file mode 100644
index 00000000000..b8abbac4ed6
--- /dev/null
+++ b/externals/mysql/vio/viotest-ssl.c
@@ -0,0 +1,151 @@
+/* Copyright (C) 2000 MySQL 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; version 2 of the License.
+
+ 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 */
+
+#include <my_global.h>
+#ifdef HAVE_OPENSSL
+#include <my_sys.h>
+#include <m_string.h>
+#include <m_ctype.h>
+#include "mysql.h"
+#include "errmsg.h"
+#include <my_dir.h>
+#include <my_getopt.h>
+#include <signal.h>
+#include <violite.h>
+
+const char *VER="0.2";
+
+
+#ifndef DBUG_OFF
+const char *default_dbug_option="d:t:O,/tmp/viotest-ssl.trace";
+#endif
+
+void
+fatal_error(const char *r)
+{
+ perror(r);
+ exit(0);
+}
+
+void
+print_usage()
+{
+ printf("viossl-test: testing SSL virtual IO. Usage:\n");
+ printf("viossl-test server-key server-cert client-key client-cert [CAfile] [CApath]\n");
+}
+
+
+int main(int argc, char **argv)
+{
+ char* server_key = 0;
+ char* server_cert = 0;
+ char* client_key = 0;
+ char* client_cert = 0;
+ char* ca_file = 0;
+ char* ca_path = 0;
+ int child_pid,sv[2];
+ struct st_VioSSLAcceptorFd* ssl_acceptor=0;
+ struct st_VioSSLConnectorFd* ssl_connector=0;
+ Vio* client_vio=0;
+ Vio* server_vio=0;
+ MY_INIT(argv[0]);
+ DBUG_PROCESS(argv[0]);
+ DBUG_PUSH(default_dbug_option);
+
+ if (argc<5)
+ {
+ print_usage();
+ return 1;
+ }
+
+ server_key = argv[1];
+ server_cert = argv[2];
+ client_key = argv[3];
+ client_cert = argv[4];
+ if (argc>5)
+ ca_file = argv[5];
+ if (argc>6)
+ ca_path = argv[6];
+ printf("Server key/cert : %s/%s\n", server_key, server_cert);
+ printf("Client key/cert : %s/%s\n", client_key, client_cert);
+ if (ca_file!=0)
+ printf("CAfile : %s\n", ca_file);
+ if (ca_path!=0)
+ printf("CApath : %s\n", ca_path);
+
+
+ if (socketpair(PF_UNIX, SOCK_STREAM, IPPROTO_IP, sv)==-1)
+ fatal_error("socketpair");
+
+ ssl_acceptor = new_VioSSLAcceptorFd(server_key, server_cert, ca_file,
+ ca_path);
+ ssl_connector = new_VioSSLConnectorFd(client_key, client_cert, ca_file,
+ ca_path);
+
+ client_vio = (Vio*)my_malloc(sizeof(struct st_vio),MYF(0));
+ client_vio->sd = sv[0];
+ sslconnect(ssl_connector,client_vio);
+ server_vio = (Vio*)my_malloc(sizeof(struct st_vio),MYF(0));
+ server_vio->sd = sv[1];
+ sslaccept(ssl_acceptor,server_vio);
+
+ printf("Socketpair: %d , %d\n", client_vio->sd, server_vio->sd);
+
+ child_pid = fork();
+ if (child_pid==-1)
+ {
+ my_free((uchar*)ssl_acceptor,MYF(0));
+ my_free((uchar*)ssl_connector,MYF(0));
+ fatal_error("fork");
+ }
+ if (child_pid==0)
+ {
+ /* child, therefore, client */
+ char xbuf[100];
+ int r = vio_ssl_read(client_vio,xbuf, sizeof(xbuf));
+ if (r<=0) {
+ my_free((uchar*)ssl_acceptor,MYF(0));
+ my_free((uchar*)ssl_connector,MYF(0));
+ fatal_error("client:SSL_read");
+ }
+ xbuf[r] = 0;
+ printf("client:got %s\n", xbuf);
+ my_free((uchar*)client_vio,MYF(0));
+ my_free((uchar*)ssl_acceptor,MYF(0));
+ my_free((uchar*)ssl_connector,MYF(0));
+ sleep(1);
+ }
+ else
+ {
+ const char* s = "Huhuhuh";
+ int r = vio_ssl_write(server_vio,(uchar*)s, strlen(s));
+ if (r<=0) {
+ my_free((uchar*)ssl_acceptor,MYF(0));
+ my_free((uchar*)ssl_connector,MYF(0));
+ fatal_error("server:SSL_write");
+ }
+ my_free((uchar*)server_vio,MYF(0));
+ my_free((uchar*)ssl_acceptor,MYF(0));
+ my_free((uchar*)ssl_connector,MYF(0));
+ sleep(1);
+ }
+ return 0;
+}
+#else /* HAVE_OPENSSL */
+
+int main() {
+return 0;
+}
+#endif /* HAVE_OPENSSL */
diff --git a/externals/mysql/vio/viotest-sslconnect.cc b/externals/mysql/vio/viotest-sslconnect.cc
new file mode 100644
index 00000000000..89e1a6e7dfe
--- /dev/null
+++ b/externals/mysql/vio/viotest-sslconnect.cc
@@ -0,0 +1,80 @@
+
+/*
+** Virtual I/O library
+** Written by Andrei Errapart <andreie@no.spam.ee>
+*/
+
+#include "all.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+void
+fatal_error( const char* r)
+{
+ perror(r);
+ exit(0);
+}
+
+void
+print_usage()
+{
+ printf("viotest-sslconnect: testing SSL virtual IO. Usage:\n");
+ printf("viotest-sslconnect key cert\n");
+}
+
+int
+main( int argc,
+ char** argv)
+{
+ char* key = 0;
+ char* cert = 0;
+
+ if (argc<3)
+ {
+ print_usage();
+ return 1;
+ }
+
+ char ip[4] = {127, 0, 0, 1};
+ unsigned long addr = (unsigned long)
+ ((unsigned long)ip[0]<<24L)|
+ ((unsigned long)ip[1]<<16L)|
+ ((unsigned long)ip[2]<< 8L)|
+ ((unsigned long)ip[3]);
+ int fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (fd<0)
+ fatal_error("socket");
+ struct sockaddr_in sa;
+ sa.sin_family = AF_INET;
+ sa.sin_port=htons(4433);
+ sa.sin_addr.s_addr=htonl(addr);
+ int sa_size = sizeof sa;
+ if (connect(fd, reinterpret_cast<const sockaddr*>(&sa), sa_size)==-1)
+ fatal_error("connect");
+ key = argv[1];
+ cert = argv[2];
+ printf("Key : %s\n", key);
+ printf("Cert : %s\n", cert);
+
+ VIO_NS::VioSSLConnectorFd* ssl_connector = new VIO_NS::VioSSLConnectorFd(cert, key,0,0);
+
+ VIO_NS::VioSSL* vio = ssl_connector->connect(fd);
+
+ char xbuf[100];
+ int r = vio->read(xbuf, sizeof(xbuf));
+ if (r<=0) {
+ delete ssl_connector;
+ delete vio;
+ fatal_error("client:SSL_read");
+ }
+ xbuf[r] = 0;
+ printf("client:got %s\n", xbuf);
+ delete vio;
+ delete ssl_connector;
+ return 0;
+}
diff --git a/externals/mysql/vio/viotest.cc b/externals/mysql/vio/viotest.cc
new file mode 100644
index 00000000000..490a9ca6694
--- /dev/null
+++ b/externals/mysql/vio/viotest.cc
@@ -0,0 +1,47 @@
+/*
+** Virtual I/O library
+** Written by Andrei Errapart <andreie@no.spam.ee>
+*/
+
+#include "all.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+
+#include <string.h>
+
+VIO_NS_USING;
+
+int
+main( int argc,
+ char** argv)
+{
+ VioFd* fs = 0;
+ VioSocket* ss = 0;
+ int fd = -1;
+ char* hh = "hshshsh\n";
+
+ DBUG_ENTER("main");
+ DBUG_PROCESS(argv[0]);
+ DBUG_PUSH("d:t");
+
+ fd = open("/dev/tty", O_WRONLY);
+ if (fd<0)
+ {
+ perror("open");
+ return 1;
+ }
+ fs = new VioFd(fd);
+ ss = new VioSocket(fd);
+ if (fs->write(hh,strlen(hh)) < 0)
+ perror("write");
+ ss->write(hh,strlen(hh));
+ printf("peer_name:%s\n", ss->peer_name());
+ printf("cipher_description:%s\n", ss->cipher_description());
+ delete fs;
+ delete ss;
+
+ DBUG_RETURN(0);
+}
+