1
0
mirror of https://github.com/mariadb-corporation/mariadb-connector-c.git synced 2025-08-07 02:42:49 +03:00
This commit is contained in:
Georg Richter
2016-01-27 06:45:49 +01:00
51 changed files with 1651 additions and 428 deletions

View File

@@ -7,7 +7,7 @@ PROJECT(mariadb-connector-c C)
SET(PACKAGE_STATUS_SUFFIX "alpha") SET(PACKAGE_STATUS_SUFFIX "alpha")
SET(CPACK_PACKAGE_VERSION_MAJOR 3) SET(CPACK_PACKAGE_VERSION_MAJOR 3)
SET(CPACK_PACKAGE_VERSION_MINOR 0) SET(CPACK_PACKAGE_VERSION_MINOR 1)
SET(CPACK_PACKAGE_VERSION_PATCH 0) SET(CPACK_PACKAGE_VERSION_PATCH 0)
SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
@@ -28,7 +28,7 @@ IF(CMAKE_VERSION VERSION_GREATER "2.9.9")
CMAKE_POLICY(SET CMP0045 OLD) CMAKE_POLICY(SET CMP0045 OLD)
ENDIF() ENDIF()
SET(MARIADB_CONNECTOR_C_COPYRIGHT "2013-2015 MariaDB Corporation Ab") SET(MARIADB_CONNECTOR_C_COPYRIGHT "2013-2016 MariaDB Corporation Ab")
### Options ### ### Options ###
IF(NOT WIN32) IF(NOT WIN32)
@@ -37,7 +37,6 @@ ELSE()
OPTION(WITH_SIGNCODE "digitally sign files" OFF) OPTION(WITH_SIGNCODE "digitally sign files" OFF)
OPTION(WITH_RTC "enables run time checks for debug builds" OFF) OPTION(WITH_RTC "enables run time checks for debug builds" OFF)
ENDIF() ENDIF()
OPTION(WITH_REMOTEIO "enables remote io support (requires libcurl)" OFF)
OPTION(WITH_EXTERNAL_ZLIB "Enables use of external zlib" OFF) OPTION(WITH_EXTERNAL_ZLIB "Enables use of external zlib" OFF)
############### ###############
@@ -53,8 +52,25 @@ IF(WITH_RTC)
SET(RTC_OPTIONS "/RTC1 /RTCc") SET(RTC_OPTIONS "/RTC1 /RTCc")
ENDIF() ENDIF()
INCLUDE(FindCURL)
IF(CURL_FOUND)
ADD_DEFINITIONS(-DHAVE_CURL=1)
ENDIF()
IF(NOT WIN32)
INCLUDE(${CMAKE_SOURCE_DIR}/cmake/FindGSSAPI.cmake)
IF(GSSAPI_FOUND)
INCLUDE_DIRECTORIES(${GSSAPI_INCS})
ENDIF()
ENDIF()
INCLUDE(${CMAKE_SOURCE_DIR}/cmake/plugins.cmake) INCLUDE(${CMAKE_SOURCE_DIR}/cmake/plugins.cmake)
IF(AUTH_GSSAPI_PLUGIN_TYPE MATCHES "STATIC")
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${GSSAPI_LIBS})
ENDIF()
IF(WIN32) IF(WIN32)
FILE(REMOVE ${CMAKE_BINARY_DIR}/win/packaging/plugin.conf) FILE(REMOVE ${CMAKE_BINARY_DIR}/win/packaging/plugin.conf)
INCLUDE(${CMAKE_SOURCE_DIR}/cmake/version_info.cmake) INCLUDE(${CMAKE_SOURCE_DIR}/cmake/version_info.cmake)
@@ -101,9 +117,9 @@ ENDIF()
# various defines for generating include/mysql_version.h # various defines for generating include/mysql_version.h
SET(PROTOCOL_VERSION 10) # we adapted new password option from PHP's mysqlnd ! SET(PROTOCOL_VERSION 10) # we adapted new password option from PHP's mysqlnd !
SET(MYSQL_CLIENT_VERSION_MAJOR "5") SET(MYSQL_CLIENT_VERSION_MAJOR "10")
SET(MYSQL_CLIENT_VERSION_MINOR "5") SET(MYSQL_CLIENT_VERSION_MINOR "1")
SET(MYSQL_CLIENT_VERSION_PATCH "2") SET(MYSQL_CLIENT_VERSION_PATCH "7")
SET(MYSQL_CLIENT_VERSION "${MYSQL_CLIENT_VERSION_MAJOR}.${MYSQL_CLIENT_VERSION_MINOR}.${MYSQL_CLIENT_VERSION_PATCH}") SET(MYSQL_CLIENT_VERSION "${MYSQL_CLIENT_VERSION_MAJOR}.${MYSQL_CLIENT_VERSION_MINOR}.${MYSQL_CLIENT_VERSION_PATCH}")
MATH(EXPR MYSQL_VERSION_ID "${MYSQL_CLIENT_VERSION_MAJOR} * 10000 + MATH(EXPR MYSQL_VERSION_ID "${MYSQL_CLIENT_VERSION_MAJOR} * 10000 +
${MYSQL_CLIENT_VERSION_MINOR} * 100 + ${MYSQL_CLIENT_VERSION_MINOR} * 100 +
@@ -133,17 +149,15 @@ ENDIF()
IF(UNIX) IF(UNIX)
SEARCH_LIBRARY(LIBNSL inet_ntoa "nsl_r;nsl")
SEARCH_LIBRARY(LIBBIND bind "bind;socket")
SEARCH_LIBRARY(LIBSOCKET setsockopt "socket")
SEARCH_LIBRARY(LIBDL dlopen "dl") SEARCH_LIBRARY(LIBDL dlopen "dl")
SEARCH_LIBRARY(LIBM floor m) SEARCH_LIBRARY(LIBM floor m)
# SEARCH_LIBRARY(LIBICONV iconv iconv)
SEARCH_LIBRARY(LIBPTHREAD pthread_getspecific "pthread;pthreads") SEARCH_LIBRARY(LIBPTHREAD pthread_getspecific "pthread;pthreads")
SET(EXTRA_LIBS "${LIBNSL}" "${LIBBIND}" "${LIBSOCKET}")
FIND_PACKAGE(Threads) FIND_PACKAGE(Threads)
SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${LIBNSL} ${LIBBIND} ${LIBICONV} SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${LIBNSL} ${LIBBIND} ${LIBICONV}
${LIBSOCKET} ${LIBDL} ${LIBM} ${LIBPTHREAD}) ${LIBSOCKET} ${LIBDL} ${LIBM} ${LIBPTHREAD})
SET(SYSTEM_LIBS ${LIBNSL} ${LIBBIND} ${LIBICONV}
${LIBSOCKET} ${LIBDL} ${LIBM} ${LIBPTHREAD})
MESSAGE(STATUS "SYSTEM_LIBS ${SYSTEM_LIBS}")
#remove possible dups from required libraries #remove possible dups from required libraries
LIST(LENGTH CMAKE_REQUIRED_LIBRARIES rllength) LIST(LENGTH CMAKE_REQUIRED_LIBRARIES rllength)
IF(${rllength} GREATER 0) IF(${rllength} GREATER 0)
@@ -178,7 +192,7 @@ INCLUDE(${CMAKE_SOURCE_DIR}/cmake/CheckFunctions.cmake)
# check for various types # check for various types
INCLUDE(${CMAKE_SOURCE_DIR}/cmake/CheckTypes.cmake) INCLUDE(${CMAKE_SOURCE_DIR}/cmake/CheckTypes.cmake)
IF(NOT WITH_SSL) IF(NOT WITH_SSL AND NOT WITH_SSL STREQUAL "OFF")
IF(WIN32) IF(WIN32)
SET(WITH_SSL "SCHANNEL") SET(WITH_SSL "SCHANNEL")
ELSE() ELSE()
@@ -245,7 +259,28 @@ ENDIF()
IF(WITH_SSL) IF(WITH_SSL)
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${SSL_LIBRARIES}) SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${SSL_LIBRARIES})
ENDIF() ENDIF()
MARK_AS_ADVANCED(SYSTEM_LIBS)
IF(NOT REMOTEIO_PLUGIN_TYPE MATCHES "OFF")
IF(CURL_FOUND)
INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIRS})
IF(REMOTEIO_PLUGIN_TYPE MATCHES "STATIC")
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${CURL_LIBRARIES})
ENDIF()
ADD_DEFINITIONS("-DHAVE_REMOTEIO=1")
ENDIF()
ENDIF()
IF(NOT WIN32)
IF(NOT AUTH_GSSAPI_PLUGIN_TYPE MATCHES "OFF")
INCLUDE(${CMAKE_SOURCE_DIR}/cmake/FindGSSAPI.cmake)
IF(GSSAPI_FOUND)
INCLUDE_DIRECTORIES(${GSSAPI_INCS})
IF(AUTH_GSSAPI_PLUGIN_TYPE MATCHES "STATIC")
SET(SYSTEM_LIBS ${SYSTEM_LIBS} ${GSSAPI_LIBS})
ENDIF()
ENDIF()
ENDIF()
ENDIF()
ADD_SUBDIRECTORY(include) ADD_SUBDIRECTORY(include)
ADD_SUBDIRECTORY(libmariadb) ADD_SUBDIRECTORY(libmariadb)
ADD_SUBDIRECTORY(plugins) ADD_SUBDIRECTORY(plugins)

View File

@@ -66,3 +66,4 @@ CHECK_INCLUDE_FILES (termio.h HAVE_TERMIO_H)
CHECK_INCLUDE_FILES (termios.h HAVE_TERMIOS_H) CHECK_INCLUDE_FILES (termios.h HAVE_TERMIOS_H)
CHECK_INCLUDE_FILES (unistd.h HAVE_UNISTD_H) CHECK_INCLUDE_FILES (unistd.h HAVE_UNISTD_H)
CHECK_INCLUDE_FILES (utime.h HAVE_UTIME_H) CHECK_INCLUDE_FILES (utime.h HAVE_UTIME_H)
CHECK_INCLUDE_FILES (ucontext.h HAVE_UCONTEXT_H)

99
cmake/FindGSSAPI.cmake Normal file
View File

@@ -0,0 +1,99 @@
# - Try to detect the GSSAPI support
# Once done this will define
#
# GSSAPI_FOUND - system supports GSSAPI
# GSSAPI_INCS - the GSSAPI include directory
# GSSAPI_LIBS - the libraries needed to use GSSAPI
# GSSAPI_FLAVOR - the type of API - MIT or HEIMDAL
# Copyright (c) 2006, Pino Toscano, <toscano.pino@tiscali.it>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if(GSSAPI_LIBS AND GSSAPI_FLAVOR)
# in cache already
set(GSSAPI_FOUND TRUE)
else(GSSAPI_LIBS AND GSSAPI_FLAVOR)
find_program(KRB5_CONFIG NAMES krb5-config PATHS
/opt/local/bin
/usr/lib/mit/bin/
ONLY_CMAKE_FIND_ROOT_PATH # this is required when cross compiling with cmake 2.6 and ignored with cmake 2.4, Alex
)
mark_as_advanced(KRB5_CONFIG)
#reset vars
set(GSSAPI_INCS)
set(GSSAPI_LIBS)
set(GSSAPI_FLAVOR)
if(KRB5_CONFIG)
set(HAVE_KRB5_GSSAPI TRUE)
exec_program(${KRB5_CONFIG} ARGS --libs gssapi RETURN_VALUE _return_VALUE OUTPUT_VARIABLE GSSAPI_LIBS)
if(_return_VALUE)
message(STATUS "GSSAPI configure check failed.")
set(HAVE_KRB5_GSSAPI FALSE)
endif(_return_VALUE)
exec_program(${KRB5_CONFIG} ARGS --cflags gssapi RETURN_VALUE _return_VALUE OUTPUT_VARIABLE GSSAPI_INCS)
string(REGEX REPLACE "(\r?\n)+$" "" GSSAPI_INCS "${GSSAPI_INCS}")
string(REGEX REPLACE " *-I" ";" GSSAPI_INCS "${GSSAPI_INCS}")
exec_program(${KRB5_CONFIG} ARGS --vendor RETURN_VALUE _return_VALUE OUTPUT_VARIABLE gssapi_flavor_tmp)
set(GSSAPI_FLAVOR_MIT)
if(gssapi_flavor_tmp MATCHES ".*Massachusetts.*")
set(GSSAPI_FLAVOR "MIT")
else(gssapi_flavor_tmp MATCHES ".*Massachusetts.*")
set(GSSAPI_FLAVOR "HEIMDAL")
endif(gssapi_flavor_tmp MATCHES ".*Massachusetts.*")
if(NOT HAVE_KRB5_GSSAPI)
if (gssapi_flavor_tmp MATCHES "Sun Microsystems.*")
message(STATUS "Solaris Kerberos does not have GSSAPI; this is normal.")
set(GSSAPI_LIBS)
set(GSSAPI_INCS)
else(gssapi_flavor_tmp MATCHES "Sun Microsystems.*")
message(WARNING "${KRB5_CONFIG} failed unexpectedly.")
endif(gssapi_flavor_tmp MATCHES "Sun Microsystems.*")
endif(NOT HAVE_KRB5_GSSAPI)
if(GSSAPI_LIBS) # GSSAPI_INCS can be also empty, so don't rely on that
set(GSSAPI_FOUND TRUE CACHE STRING "")
message(STATUS "Found GSSAPI: ${GSSAPI_LIBS}")
set(GSSAPI_INCS ${GSSAPI_INCS} CACHE STRING "")
set(GSSAPI_LIBS ${GSSAPI_LIBS} CACHE STRING "")
set(GSSAPI_FLAVOR ${GSSAPI_FLAVOR} CACHE STRING "")
mark_as_advanced(GSSAPI_INCS GSSAPI_LIBS GSSAPI_FLAVOR)
endif(GSSAPI_LIBS)
endif(KRB5_CONFIG)
endif(GSSAPI_LIBS AND GSSAPI_FLAVOR)

View File

@@ -15,7 +15,7 @@ ELSE()
ENDIF() ENDIF()
IF(APPLE) IF(APPLE)
find_library(ICONV_LIBRARIES NAMES iconv libiconv c PATHS find_library(ICONV_LIBRARIES NAMES iconv libiconv PATHS
/opt/local/lib/ /opt/local/lib/
/usr/lib/ /usr/lib/
NO_CMAKE_SYSTEM_PATH) NO_CMAKE_SYSTEM_PATH)

View File

@@ -2,7 +2,7 @@
MACRO(REGISTER_PLUGIN name source struct type target allow) MACRO(REGISTER_PLUGIN name source struct type target allow)
SET(PLUGIN_TYPE ${${name}}) SET(PLUGIN_TYPE ${${name}})
IF(NOT PLUGIN_TYPE STREQUAL "OFF") IF(NOT PLUGIN_TYPE STREQUAL "OFF" AND NOT PLUGIN_TYPE)
SET(PLUGIN_TYPE ${type}) SET(PLUGIN_TYPE ${type})
ENDIF() ENDIF()
IF(PLUGINS) IF(PLUGINS)
@@ -18,6 +18,7 @@ MACRO(REGISTER_PLUGIN name source struct type target allow)
SET(${name}_PLUGIN_SOURCE ${source}) SET(${name}_PLUGIN_SOURCE ${source})
SET(${name}_PLUGIN_CHG ${allow}) SET(${name}_PLUGIN_CHG ${allow})
SET(PLUGINS ${PLUGINS} "${name}") SET(PLUGINS ${PLUGINS} "${name}")
ADD_DEFINITIONS(-DHAVE_${name}=1)
ENDMACRO() ENDMACRO()
MARK_AS_ADVANCED(PLUGINS) MARK_AS_ADVANCED(PLUGINS)
@@ -34,18 +35,31 @@ REGISTER_PLUGIN("AUTH_NATIVE" "${CMAKE_SOURCE_DIR}/plugins/auth/my_auth.c" "nati
REGISTER_PLUGIN("AUTH_OLDPASSWORD" "${CMAKE_SOURCE_DIR}/plugins/auth/old_password.c" "old_password_client_plugin" "DYNAMIC" "old_password" 1) REGISTER_PLUGIN("AUTH_OLDPASSWORD" "${CMAKE_SOURCE_DIR}/plugins/auth/old_password.c" "old_password_client_plugin" "DYNAMIC" "old_password" 1)
REGISTER_PLUGIN("AUTH_DIALOG" "${CMAKE_SOURCE_DIR}/plugins/auth/dialog.c" "auth_dialog_plugin" "DYNAMIC" dialog 1) REGISTER_PLUGIN("AUTH_DIALOG" "${CMAKE_SOURCE_DIR}/plugins/auth/dialog.c" "auth_dialog_plugin" "DYNAMIC" dialog 1)
REGISTER_PLUGIN("AUTH_CLEARTEXT" "${CMAKE_SOURCE_DIR}/plugins/auth/mariadb_clear_text.c" "auth_cleartext_plugin" "DYNAMIC" "mysql_clear_password" 1) REGISTER_PLUGIN("AUTH_CLEARTEXT" "${CMAKE_SOURCE_DIR}/plugins/auth/mariadb_clear_text.c" "auth_cleartext_plugin" "DYNAMIC" "mysql_clear_password" 1)
IF(WIN32)
SET(GSSAPI_SOURCES ${CMAKE_SOURCE_DIR}/plugins/auth/auth_gssapi_client.c ${CMAKE_SOURCE_DIR}/plugins/auth/sspi_client.c ${CMAKE_SOURCE_DIR}/plugins/auth/sspi_errmsg.c)
REGISTER_PLUGIN("AUTH_GSSAPI" "${GSSAPI_SOURCES}" "auth_gssapi_plugin" "DYNAMIC" "auth_gssapi_client" 1)
ELSE()
IF(GSSAPI_FOUND)
SET(GSSAPI_SOURCES ${CMAKE_SOURCE_DIR}/plugins/auth/auth_gssapi_client.c ${CMAKE_SOURCE_DIR}/plugins/auth/gssapi_client.c ${CMAKE_SOURCE_DIR}/plugins/auth/gssapi_errmsg.c)
REGISTER_PLUGIN("AUTH_GSSAPI" "${GSSAPI_SOURCES}" "auth_gssapi_plugin" "DYNAMIC" "auth_gssapi_client" 1)
ENDIF()
ENDIF()
#Remote_IO #Remote_IO
IF(CURL_FOUND) IF(CURL_FOUND)
REGISTER_PLUGIN("REMOTEIO" "${CMAKE_SOURCE_DIR}/plugins/io/remote_io.c" "remote_io_plugin" "DYNAMIC" "remote_io" 1) IF(WIN32)
REGISTER_PLUGIN("REMOTEIO" "${CMAKE_SOURCE_DIR}/plugins/io/remote_io.c" "remote_io_plugin" "DYNAMIC" "remote_io" 1)
ELSE()
REGISTER_PLUGIN("REMOTEIO" "${CMAKE_SOURCE_DIR}/plugins/io/remote_io.c" "remote_io_plugin" "STATIC" "remote_io" 1)
ENDIF()
ENDIF() ENDIF()
#Trace #Trace
REGISTER_PLUGIN("TRACE_EXAMPLE" "${CMAKE_SOURCE_DIR}/plugins/trace/trace_example.c" "trace_example_plugin" "DYNAMIC" "trace_example" 1) REGISTER_PLUGIN("TRACE_EXAMPLE" "${CMAKE_SOURCE_DIR}/plugins/trace/trace_example.c" "trace_example_plugin" "DYNAMIC" "trace_example" 1)
#Connection #Connection
REGISTER_PLUGIN("REPLICATION" "${CMAKE_SOURCE_DIR}/plugins/connection/replication.c" "connection_replication_plugin" "DYNAMIC" "" 1) REGISTER_PLUGIN("REPLICATION" "${CMAKE_SOURCE_DIR}/plugins/connection/replication.c" "connection_replication_plugin" "DYNAMIC" "replication" 1)
REGISTER_PLUGIN("AURORA" "${CMAKE_SOURCE_DIR}/plugins/connection/aurora.c" "connection_aurora_plugin" "DYNAMIC" "" 1) REGISTER_PLUGIN("AURORA" "${CMAKE_SOURCE_DIR}/plugins/connection/aurora.c" "connection_aurora_plugin" "DYNAMIC" "aurora" 1)
# Allow registration of additional plugins # Allow registration of additional plugins
IF(PLUGIN_CONF_FILE) IF(PLUGIN_CONF_FILE)

View File

@@ -210,7 +210,9 @@ inline double ulonglong2double(ulonglong value)
#define HAVE_PUTENV #define HAVE_PUTENV
#define HAVE_SELECT #define HAVE_SELECT
#define HAVE_SETLOCALE #define HAVE_SETLOCALE
#ifndef HAVE_SOCKET
#define HAVE_SOCKET /* Giangi */ #define HAVE_SOCKET /* Giangi */
#endif
#define HAVE_FLOAT_H #define HAVE_FLOAT_H
#define HAVE_LIMITS_H #define HAVE_LIMITS_H
#define HAVE_STDDEF_H #define HAVE_STDDEF_H

View File

@@ -56,6 +56,7 @@ struct st_mysql_options_extension {
commands in one packet */ commands in one packet */
char *url; /* for connection handler we need to save URL for reconnect */ char *url; /* for connection handler we need to save URL for reconnect */
my_bool read_only; my_bool read_only;
char *connection_handler;
HASH userdata; HASH userdata;
}; };

View File

@@ -28,12 +28,6 @@ typedef struct st_ma_pvio_methods PVIO_METHODS;
#define IS_MYSQL_ASYNC_ACTIVE(a) \ #define IS_MYSQL_ASYNC_ACTIVE(a) \
(IS_MYSQL_ASYNC(a)&& (a)->options.extension->async_context->active) (IS_MYSQL_ASYNC(a)&& (a)->options.extension->async_context->active)
#ifndef ssl_defined
#define ssl_defined
struct st_ma_pvio_ssl;
typedef struct st_ma_pvio_ssl MARIADB_SSL;
#endif
enum enum_pvio_timeout { enum enum_pvio_timeout {
PVIO_CONNECT_TIMEOUT= 0, PVIO_CONNECT_TIMEOUT= 0,
PVIO_READ_TIMEOUT, PVIO_READ_TIMEOUT,

View File

@@ -151,5 +151,6 @@ const char *ma_pvio_ssl_cipher(MARIADB_SSL *cssl);
my_bool ma_pvio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, const char *fp_list); my_bool ma_pvio_ssl_check_fp(MARIADB_SSL *cssl, const char *fp, const char *fp_list);
my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio); my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio);
my_bool ma_pvio_ssl_get_protocol_version(MARIADB_SSL *cssl, struct st_ssl_version *version); my_bool ma_pvio_ssl_get_protocol_version(MARIADB_SSL *cssl, struct st_ssl_version *version);
void ma_pvio_ssl_end();
#endif /* _ma_ssl_h_ */ #endif /* _ma_ssl_h_ */

View File

@@ -46,6 +46,7 @@
#cmakedefine HAVE_TERMIOS_H 1 #cmakedefine HAVE_TERMIOS_H 1
#cmakedefine HAVE_UNISTD_H 1 #cmakedefine HAVE_UNISTD_H 1
#cmakedefine HAVE_UTIME_H 1 #cmakedefine HAVE_UTIME_H 1
#cmakedefine HAVE_UCONTEXT_H 1
/* /*
* function definitions - processed in LibmysqlFunctions.txt * function definitions - processed in LibmysqlFunctions.txt

View File

@@ -31,7 +31,7 @@
#define MY_CONTEXT_USE_X86_64_GCC_ASM #define MY_CONTEXT_USE_X86_64_GCC_ASM
#elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__i386__) #elif defined(__GNUC__) && __GNUC__ >= 3 && defined(__i386__)
#define MY_CONTEXT_USE_I386_GCC_ASM #define MY_CONTEXT_USE_I386_GCC_ASM
#elif defined(HAVE_UCONTEXT) #elif defined(HAVE_UCONTEXT_H)
#define MY_CONTEXT_USE_UCONTEXT #define MY_CONTEXT_USE_UCONTEXT
#else #else
#define MY_CONTEXT_DISABLE #define MY_CONTEXT_DISABLE

View File

@@ -213,22 +213,25 @@ extern unsigned int mariadb_deinitialize_ssl;
MYSQL_DATABASE_DRIVER=7000, MYSQL_DATABASE_DRIVER=7000,
MARIADB_OPT_SSL_FP, /* single finger print for server certificate verification */ MARIADB_OPT_SSL_FP, /* single finger print for server certificate verification */
MARIADB_OPT_SSL_FP_LIST, /* finger print white list for server certificate verification */ MARIADB_OPT_SSL_FP_LIST, /* finger print white list for server certificate verification */
MARIADB_OPT_SSL_PASSWORD, /* password for encrypted certificates */ MARIADB_OPT_SSL_PASSPHRASE, /* passphrase for encrypted certificates */
MARIADB_OPT_COM_MULTI,
MARIADB_OPT_CONNECTION_READ_ONLY, MARIADB_OPT_CONNECTION_READ_ONLY,
MYSQL_OPT_CONNECT_ATTRS, /* for mysql_get_optionv */ MYSQL_OPT_CONNECT_ATTRS, /* for mysql_get_optionv */
MARIADB_OPT_USERDATA MARIADB_OPT_USERDATA,
MARIADB_OPT_CONNECTION_HANDLER,
MARIADB_OPT_COM_MULTI,
}; };
enum mariadb_value { enum mariadb_value {
MARIADB_CHARSET_ID, MARIADB_CHARSET_ID,
MARIADB_CHARSET_INFO,
MARIADB_CHARSET_NAME, MARIADB_CHARSET_NAME,
MARIADB_CLIENT_ERRORS, MARIADB_CLIENT_ERRORS,
MARIADB_CLIENT_VERSION, MARIADB_CLIENT_VERSION,
MARIADB_CLIENT_VERSION_ID, MARIADB_CLIENT_VERSION_ID,
MARIADB_CONNECTION_ASYNC_TIMEOUT, MARIADB_CONNECTION_ASYNC_TIMEOUT,
MARIADB_CONNECTION_ASYNC_TIMEOUT_MS, MARIADB_CONNECTION_ASYNC_TIMEOUT_MS,
MARIADB_CONNECTION_CHARSET_INFO,
MARIADB_CONNECTION_ERROR,
MARIADB_CONNECTION_ERROR_ID,
MARIADB_CONNECTION_HOST, MARIADB_CONNECTION_HOST,
MARIADB_CONNECTION_INFO, MARIADB_CONNECTION_INFO,
MARIADB_CONNECTION_PORT, MARIADB_CONNECTION_PORT,
@@ -239,7 +242,9 @@ extern unsigned int mariadb_deinitialize_ssl;
MARIADB_CONNECTION_SERVER_VERSION, MARIADB_CONNECTION_SERVER_VERSION,
MARIADB_CONNECTION_SERVER_VERSION_ID, MARIADB_CONNECTION_SERVER_VERSION_ID,
MARIADB_CONNECTION_SOCKET, MARIADB_CONNECTION_SOCKET,
MARIADB_CONNECTION_SQLSTATE,
MARIADB_CONNECTION_SSL_CIPHER, MARIADB_CONNECTION_SSL_CIPHER,
MARIADB_SSL_LIBRARY,
MARIADB_CONNECTION_SSL_VERSION, MARIADB_CONNECTION_SSL_VERSION,
MARIADB_CONNECTION_SSL_VERSION_ID, MARIADB_CONNECTION_SSL_VERSION_ID,
MARIADB_CONNECTION_TYPE, MARIADB_CONNECTION_TYPE,
@@ -281,7 +286,7 @@ struct st_mysql_options {
unsigned long max_allowed_packet; unsigned long max_allowed_packet;
my_bool use_ssl; /* if to use SSL or not */ my_bool use_ssl; /* if to use SSL or not */
my_bool compress,named_pipe; my_bool compress,named_pipe;
my_bool unused_1, unused_2, unused_3, unused_4; my_bool reconnect, unused_1, unused_2, unused_3;
enum mysql_option methods_to_use; enum mysql_option methods_to_use;
char *bind_address; char *bind_address;
my_bool secure_auth; my_bool secure_auth;
@@ -318,12 +323,12 @@ struct st_mysql_options {
unsigned int warning_count; /* warning count, added in 4.1 protocol */ unsigned int warning_count; /* warning count, added in 4.1 protocol */
struct st_mysql_options options; struct st_mysql_options options;
enum mysql_status status; enum mysql_status status;
my_bool free_me; /* If free in mysql_close */ my_bool free_me; /* If free in mysql_close */
my_bool reconnect; /* set to 1 if automatic reconnect */ my_bool unused_1;
char scramble_buff[20+ 1]; char scramble_buff[20+ 1];
/* madded after 3.23.58 */ /* madded after 3.23.58 */
my_bool unused_1; my_bool unused_2;
void *unused_2, *unused_3, *unused_4, *unused_5; void *unused_3, *unused_4, *unused_5, *unused_6;
LIST *stmts; LIST *stmts;
const struct st_mysql_methods *methods; const struct st_mysql_methods *methods;
void *thd; void *thd;
@@ -438,7 +443,6 @@ const char * STDCALL mysql_character_set_name(MYSQL *mysql);
void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *cs); void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *cs);
int STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname); int STDCALL mysql_set_character_set(MYSQL *mysql, const char *csname);
int STDCALL mariadb_flush_multi_command(MYSQL *mysql);
my_bool STDCALL mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *arg, ...); my_bool STDCALL mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *arg, ...);
my_bool STDCALL mariadb_get_info(MYSQL *mysql, enum mariadb_value value, void *arg); my_bool STDCALL mariadb_get_info(MYSQL *mysql, enum mariadb_value value, void *arg);
MYSQL * STDCALL mysql_init(MYSQL *mysql); MYSQL * STDCALL mysql_init(MYSQL *mysql);

View File

@@ -151,11 +151,11 @@ typedef char *(*mysql_authentication_dialog_ask_t)(struct st_mysql *mysql,
#include <mariadb/ma_io.h> #include <mariadb/ma_io.h>
/* Remote IO plugin */ /* Remote IO plugin */
struct st_mysql_client_plugin_REMOTEIO typedef struct st_mysql_client_plugin_REMOTEIO
{ {
MYSQL_CLIENT_PLUGIN_HEADER MYSQL_CLIENT_PLUGIN_HEADER
struct st_rio_methods *methods; struct st_rio_methods *methods;
}; } MARIADB_REMOTEIO_PLUGIN;
#endif #endif
/******** using plugins ************/ /******** using plugins ************/

View File

@@ -34,7 +34,6 @@ SET(EXPORT_SYMBOLS
mariadb_dyncol_val_double mariadb_dyncol_val_double
mariadb_dyncol_val_long mariadb_dyncol_val_long
mariadb_dyncol_val_str mariadb_dyncol_val_str
mariadb_flush_multi_command
mariadb_get_charset_by_name mariadb_get_charset_by_name
mariadb_get_charset_by_nr mariadb_get_charset_by_nr
mariadb_get_info mariadb_get_info
@@ -113,7 +112,7 @@ SET(EXPORT_SYMBOLS
mysql_list_tables mysql_list_tables
mysql_list_tables_cont mysql_list_tables_cont
mysql_list_tables_start mysql_list_tables_start
mysql_load_plugin; mysql_load_plugin
mysql_load_plugin_v mysql_load_plugin_v
mysql_more_results mysql_more_results
mysql_next_result mysql_next_result
@@ -403,7 +402,6 @@ ENDIF()
ADD_LIBRARY(mariadbclient STATIC ${ariadbclient_RC} $<TARGET_OBJECTS:mariadb_obj> ${EMPTY_FILE} ${EXPORT_LINK}) ADD_LIBRARY(mariadbclient STATIC ${ariadbclient_RC} $<TARGET_OBJECTS:mariadb_obj> ${EMPTY_FILE} ${EXPORT_LINK})
TARGET_LINK_LIBRARIES(mariadbclient ${SYSTEM_LIBS}) TARGET_LINK_LIBRARIES(mariadbclient ${SYSTEM_LIBS})
ADD_LIBRARY(libmariadb SHARED ${libmariadb_RC} $<TARGET_OBJECTS:mariadb_obj> ${EMPTY_FILE} ${EXPORT_LINK}) ADD_LIBRARY(libmariadb SHARED ${libmariadb_RC} $<TARGET_OBJECTS:mariadb_obj> ${EMPTY_FILE} ${EXPORT_LINK})
TARGET_LINK_LIBRARIES(libmariadb ${SYSTEM_LIBS}) TARGET_LINK_LIBRARIES(libmariadb ${SYSTEM_LIBS})
IF(UNIX) IF(UNIX)

View File

@@ -107,6 +107,10 @@ extern int mthd_stmt_fetch_to_bind(MYSQL_STMT *stmt, unsigned char *row);
extern int mthd_stmt_read_all_rows(MYSQL_STMT *stmt); extern int mthd_stmt_read_all_rows(MYSQL_STMT *stmt);
extern void mthd_stmt_flush_unbuffered(MYSQL_STMT *stmt); extern void mthd_stmt_flush_unbuffered(MYSQL_STMT *stmt);
extern unsigned char *mysql_net_store_length(unsigned char *packet, size_t length); extern unsigned char *mysql_net_store_length(unsigned char *packet, size_t length);
extern void
my_context_install_suspend_resume_hook(struct mysql_async_context *b,
void (*hook)(my_bool, void *),
void *user_data);
uint mysql_port=0; uint mysql_port=0;
my_string mysql_unix_port=0; my_string mysql_unix_port=0;
@@ -132,7 +136,7 @@ struct st_mysql_methods MARIADB_DEFAULT_METHODS;
#define native_password_plugin_name "mysql_native_password" #define native_password_plugin_name "mysql_native_password"
#define IS_CONNHDLR_ACTIVE(mysql)\ #define IS_CONNHDLR_ACTIVE(mysql)\
((mysql)->net.conn_hdlr && (mysql)->net.conn_hdlr->active) (((mysql)->net.conn_hdlr))
static void end_server(MYSQL *mysql); static void end_server(MYSQL *mysql);
static void mysql_close_memory(MYSQL *mysql); static void mysql_close_memory(MYSQL *mysql);
@@ -1169,7 +1173,7 @@ mysql_init(MYSQL *mysql)
#ifdef ENABLED_LOCAL_INFILE #ifdef ENABLED_LOCAL_INFILE
mysql->options.client_flag|= CLIENT_LOCAL_FILES; mysql->options.client_flag|= CLIENT_LOCAL_FILES;
#endif #endif
mysql->reconnect= 0; mysql->options.reconnect= 0;
return mysql; return mysql;
} }
@@ -1304,18 +1308,26 @@ mysql_real_connect(MYSQL *mysql, const char *host, const char *user,
uint port, const char *unix_socket,unsigned long client_flag) uint port, const char *unix_socket,unsigned long client_flag)
{ {
char *end; char *end;
char *connection_handler= (mysql->options.extension) ?
mysql->options.extension->connection_handler : 0;
if (!mysql->methods) if (!mysql->methods)
mysql->methods= &MARIADB_DEFAULT_METHODS; mysql->methods= &MARIADB_DEFAULT_METHODS;
if (host && (end= strstr(host, "://"))) if (connection_handler ||
(host && (end= strstr(host, "://"))))
{ {
MARIADB_CONNECTION_PLUGIN *plugin; MARIADB_CONNECTION_PLUGIN *plugin;
char plugin_name[64]; char plugin_name[64];
bzero(plugin_name, 64); if (!connection_handler || !connection_handler[0])
strncpy(plugin_name, host, MIN(end - host, 63)); {
end+= 3; bzero(plugin_name, 64);
strncpy(plugin_name, host, MIN(end - host, 63));
end+= 3;
}
else
strncpy(plugin_name, connection_handler, MIN(63, strlen(connection_handler)));
if (!(plugin= (MARIADB_CONNECTION_PLUGIN *)mysql_client_find_plugin(mysql, plugin_name, MARIADB_CLIENT_CONNECTION_PLUGIN))) if (!(plugin= (MARIADB_CONNECTION_PLUGIN *)mysql_client_find_plugin(mysql, plugin_name, MARIADB_CLIENT_CONNECTION_PLUGIN)))
return NULL; return NULL;
@@ -1332,7 +1344,15 @@ mysql_real_connect(MYSQL *mysql, const char *host, const char *user,
mysql->net.conn_hdlr->plugin= plugin; mysql->net.conn_hdlr->plugin= plugin;
if (plugin && plugin->connect) if (plugin && plugin->connect)
return plugin->connect(mysql, end, user, passwd, db, port, unix_socket, client_flag); {
MYSQL *my= plugin->connect(mysql, end, user, passwd, db, port, unix_socket, client_flag);
if (!my)
{
my_free(mysql->net.conn_hdlr);
mysql->net.conn_hdlr= NULL;
}
return my;
}
} }
return mysql->methods->db_connect(mysql, host, user, passwd, return mysql->methods->db_connect(mysql, host, user, passwd,
@@ -1678,8 +1698,8 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
char **end= begin + mysql->options.init_command->elements; char **end= begin + mysql->options.init_command->elements;
/* Avoid reconnect in mysql_real_connect */ /* Avoid reconnect in mysql_real_connect */
my_bool save_reconnect= mysql->reconnect; my_bool save_reconnect= mysql->options.reconnect;
mysql->reconnect= 0; mysql->options.reconnect= 0;
for (;begin < end; begin++) for (;begin < end; begin++)
{ {
@@ -1693,7 +1713,7 @@ MYSQL *mthd_my_real_connect(MYSQL *mysql, const char *host, const char *user,
mysql_free_result(res); mysql_free_result(res);
} while (!mysql_next_result(mysql)); } while (!mysql_next_result(mysql));
} }
mysql->reconnect= save_reconnect; mysql->options.reconnect= save_reconnect;
} }
strmov(mysql->net.sqlstate, "00000"); strmov(mysql->net.sqlstate, "00000");
@@ -1748,13 +1768,13 @@ my_bool STDCALL mysql_reconnect(MYSQL *mysql)
DBUG_ENTER("mysql_reconnect"); DBUG_ENTER("mysql_reconnect");
/* check if connection handler is active */ /* check if connection handler is active */
if (IS_CONNHDLR_ACTIVE(mysql)) if (IS_CONNHDLR_ACTIVE(mysql))
{ {
if (mysql->net.conn_hdlr->plugin && mysql->net.conn_hdlr->plugin->connect) if (mysql->net.conn_hdlr->plugin && mysql->net.conn_hdlr->plugin->reconnect)
DBUG_RETURN(mysql->net.conn_hdlr->plugin->reconnect(mysql)); DBUG_RETURN(mysql->net.conn_hdlr->plugin->reconnect(mysql));
} }
if (!mysql->reconnect || if (!mysql->options.reconnect ||
(mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info) (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info)
{ {
/* Allow reconnect next time */ /* Allow reconnect next time */
@@ -1811,7 +1831,6 @@ my_bool STDCALL mysql_reconnect(MYSQL *mysql)
} }
} }
tmp_mysql.reconnect= mysql->reconnect;
tmp_mysql.free_me= mysql->free_me; tmp_mysql.free_me= mysql->free_me;
tmp_mysql.stmts= mysql->stmts; tmp_mysql.stmts= mysql->stmts;
mysql->stmts= NULL; mysql->stmts= NULL;
@@ -1972,6 +1991,7 @@ static void mysql_close_options(MYSQL *mysql)
my_free(mysql->options.extension->ssl_fp_list); my_free(mysql->options.extension->ssl_fp_list);
my_free(mysql->options.extension->ssl_pw); my_free(mysql->options.extension->ssl_pw);
my_free(mysql->options.extension->url); my_free(mysql->options.extension->url);
my_free(mysql->options.extension->connection_handler);
if(hash_inited(&mysql->options.extension->connect_attrs)) if(hash_inited(&mysql->options.extension->connect_attrs))
hash_free(&mysql->options.extension->connect_attrs); hash_free(&mysql->options.extension->connect_attrs);
if (hash_inited(&mysql->options.extension->userdata)) if (hash_inited(&mysql->options.extension->userdata))
@@ -2024,8 +2044,9 @@ void mysql_close_slow_part(MYSQL *mysql)
{ {
free_old_query(mysql); free_old_query(mysql);
mysql->status=MYSQL_STATUS_READY; /* Force command */ mysql->status=MYSQL_STATUS_READY; /* Force command */
mysql->reconnect=0; mysql->options.reconnect=0;
simple_command(mysql, COM_QUIT,NullS,0,1,0); if (mysql->net.pvio && mysql->net.buff)
simple_command(mysql, COM_QUIT,NullS,0,1,0);
end_server(mysql); end_server(mysql);
} }
} }
@@ -2036,13 +2057,11 @@ mysql_close(MYSQL *mysql)
DBUG_ENTER("mysql_close"); DBUG_ENTER("mysql_close");
if (mysql) /* Some simple safety */ if (mysql) /* Some simple safety */
{ {
if (mysql->net.conn_hdlr)
if (IS_CONNHDLR_ACTIVE(mysql))
{ {
void *p= (void *)mysql->net.conn_hdlr; MA_CONNECTION_HANDLER *p= mysql->net.conn_hdlr;
mysql->net.conn_hdlr->plugin->close(mysql); p->plugin->close(mysql);
my_free(p); my_free(p);
DBUG_VOID_RETURN;
} }
if (mysql->methods) if (mysql->methods)
@@ -2160,6 +2179,8 @@ mysql_real_query(MYSQL *mysql, const char *query, size_t length)
if (OPT_HAS_EXT_VAL(mysql, multi_command)) if (OPT_HAS_EXT_VAL(mysql, multi_command))
is_multi= mysql->options.extension->multi_command; is_multi= mysql->options.extension->multi_command;
if (length == -1)
length= strlen(query);
free_old_query(mysql); free_old_query(mysql);
@@ -2566,7 +2587,7 @@ mysql_ping(MYSQL *mysql)
rc= simple_command(mysql, COM_PING,0,0,0,0); rc= simple_command(mysql, COM_PING,0,0,0,0);
/* if connection was terminated and reconnect is true, try again */ /* if connection was terminated and reconnect is true, try again */
if (rc!=0 && mysql->reconnect) if (rc!=0 && mysql->options.reconnect)
rc= simple_command(mysql, COM_PING,0,0,0,0); rc= simple_command(mysql, COM_PING,0,0,0,0);
return rc; return rc;
} }
@@ -2704,15 +2725,9 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
mysql->options.charset_name=my_strdup((char *)arg1,MYF(MY_WME)); mysql->options.charset_name=my_strdup((char *)arg1,MYF(MY_WME));
break; break;
case MYSQL_OPT_RECONNECT: case MYSQL_OPT_RECONNECT:
mysql->reconnect= *(uint *)arg1; mysql->options.reconnect= *(uint *)arg1;
break; break;
case MYSQL_OPT_PROTOCOL: case MYSQL_OPT_PROTOCOL:
#ifdef _WIN32
if (*(uint *)arg1 > MYSQL_PROTOCOL_PIPE)
#else
if (*(uint *)arg1 > MYSQL_PROTOCOL_SOCKET)
#endif
goto end;
mysql->options.protocol= *(uint *)arg1; mysql->options.protocol= *(uint *)arg1;
break; break;
case MYSQL_OPT_READ_TIMEOUT: case MYSQL_OPT_READ_TIMEOUT:
@@ -2722,7 +2737,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
mysql->options.write_timeout= *(uint *)arg1; mysql->options.write_timeout= *(uint *)arg1;
break; break;
case MYSQL_REPORT_DATA_TRUNCATION: case MYSQL_REPORT_DATA_TRUNCATION:
mysql->options.report_data_truncation= *(uint *)arg1; mysql->options.report_data_truncation= *(my_bool *)arg1;
break; break;
case MYSQL_PROGRESS_CALLBACK: case MYSQL_PROGRESS_CALLBACK:
if (!mysql->options.extension) if (!mysql->options.extension)
@@ -2807,7 +2822,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
break; break;
case MYSQL_OPT_SSL_VERIFY_SERVER_CERT: case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
if (*(uint *)arg1) if (*(my_bool *)arg1)
mysql->options.client_flag |= CLIENT_SSL_VERIFY_SERVER_CERT; mysql->options.client_flag |= CLIENT_SSL_VERIFY_SERVER_CERT;
else else
mysql->options.client_flag &= ~CLIENT_SSL_VERIFY_SERVER_CERT; mysql->options.client_flag &= ~CLIENT_SSL_VERIFY_SERVER_CERT;
@@ -2865,6 +2880,9 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
mysql->options.extension->connect_attrs_len= 0; mysql->options.extension->connect_attrs_len= 0;
} }
break; break;
case MARIADB_OPT_CONNECTION_HANDLER:
OPT_SET_EXTENDED_VALUE_STR(&mysql->options, connection_handler, (char *)arg1);
break;
case MARIADB_OPT_USERDATA: case MARIADB_OPT_USERDATA:
{ {
void *data= va_arg(ap, void *); void *data= va_arg(ap, void *);
@@ -2881,13 +2899,27 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
if (!hash_inited(&mysql->options.extension->userdata)) if (!hash_inited(&mysql->options.extension->userdata))
{ {
if (_hash_init(&mysql->options.extension->userdata, if (_hash_init(&mysql->options.extension->userdata,
0, 0, 0, ma_get_hash_keyval, ma_hash_free, 0) || 0, 0, 0, ma_get_hash_keyval, ma_hash_free, 0))
!(buffer= (uchar *)my_malloc(strlen(key) + 1 + sizeof(void *), MYF(MY_ZEROFILL))))
{ {
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
goto end; goto end;
} }
} }
/* check if key is already in buffer */
if (p= (uchar *)hash_search(&mysql->options.extension->userdata, (uchar *)key,
(uint)strlen((char *)key)))
{
p+= strlen(key) + 1;
memcpy(p, &data, sizeof(void *));
break;
}
if (!(buffer= (uchar *)my_malloc(strlen(key) + 1 + sizeof(void *), MYF(MY_ZEROFILL))))
{
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
goto end;
}
p= buffer; p= buffer;
strcpy(p, key); strcpy(p, key);
p+= strlen(key) + 1; p+= strlen(key) + 1;
@@ -2972,7 +3004,7 @@ mysql_optionsv(MYSQL *mysql,enum mysql_option option, ...)
case MARIADB_OPT_SSL_FP_LIST: case MARIADB_OPT_SSL_FP_LIST:
OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_fp_list, (char *)arg1); OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_fp_list, (char *)arg1);
break; break;
case MARIADB_OPT_SSL_PASSWORD: case MARIADB_OPT_SSL_PASSPHRASE:
OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_pw, (char *)arg1); OPT_SET_EXTENDED_VALUE_STR(&mysql->options, ssl_pw, (char *)arg1);
break; break;
case MARIADB_OPT_COM_MULTI: case MARIADB_OPT_COM_MULTI:
@@ -3046,7 +3078,7 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...)
*((char **)arg)= mysql->options.charset_name; *((char **)arg)= mysql->options.charset_name;
break; break;
case MYSQL_OPT_RECONNECT: case MYSQL_OPT_RECONNECT:
*((uint *)arg)= mysql->reconnect; *((my_bool *)arg)= mysql->options.reconnect;
break; break;
case MYSQL_OPT_PROTOCOL: case MYSQL_OPT_PROTOCOL:
*((uint *)arg)= mysql->options.protocol; *((uint *)arg)= mysql->options.protocol;
@@ -3058,7 +3090,7 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...)
*((uint *)arg)= mysql->options.write_timeout; *((uint *)arg)= mysql->options.write_timeout;
break; break;
case MYSQL_REPORT_DATA_TRUNCATION: case MYSQL_REPORT_DATA_TRUNCATION:
*((uint *)arg)= mysql->options.report_data_truncation; *((my_bool *)arg)= mysql->options.report_data_truncation;
break; break;
case MYSQL_PROGRESS_CALLBACK: case MYSQL_PROGRESS_CALLBACK:
*((void (**)(const MYSQL *, uint, uint, double, const char *, uint))arg)= *((void (**)(const MYSQL *, uint, uint, double, const char *, uint))arg)=
@@ -3152,13 +3184,12 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...)
case MARIADB_OPT_SSL_FP_LIST: case MARIADB_OPT_SSL_FP_LIST:
*((char **)arg)= mysql->options.extension ? mysql->options.extension->ssl_fp_list : NULL; *((char **)arg)= mysql->options.extension ? mysql->options.extension->ssl_fp_list : NULL;
break; break;
case MARIADB_OPT_SSL_PASSWORD: case MARIADB_OPT_SSL_PASSPHRASE:
*((char **)arg)= mysql->options.extension ? mysql->options.extension->ssl_pw : NULL; *((char **)arg)= mysql->options.extension ? mysql->options.extension->ssl_pw : NULL;
break; break;
/* todo
case MARIADB_OPT_CONNECTION_READ_ONLY: case MARIADB_OPT_CONNECTION_READ_ONLY:
*((my_bool *)arg)= mysql->options.extension ? mysql->options.extension->read_only : 0;
break; break;
*/
case MARIADB_OPT_USERDATA: case MARIADB_OPT_USERDATA:
/* nysql_get_optionv(mysql, MARIADB_OPT_USERDATA, key, value) */ /* nysql_get_optionv(mysql, MARIADB_OPT_USERDATA, key, value) */
{ {
@@ -3177,6 +3208,9 @@ mysql_get_optionv(MYSQL *mysql, enum mysql_option option, void *arg, ...)
*((void **)data)= NULL; *((void **)data)= NULL;
} }
break; break;
case MARIADB_OPT_CONNECTION_HANDLER:
*((char **)arg)= mysql->options.extension ? mysql->options.extension->connection_handler : NULL;
break;
default: default:
va_end(ap); va_end(ap);
DBUG_RETURN(-1); DBUG_RETURN(-1);
@@ -3473,7 +3507,7 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)),
return(rc); return(rc);
} }
void STDCALL mysql_server_end() void STDCALL mysql_server_end(void)
{ {
if (!mysql_client_init) if (!mysql_client_init)
return; return;
@@ -3483,6 +3517,9 @@ void STDCALL mysql_server_end()
list_free(pvio_callback, 0); list_free(pvio_callback, 0);
if (my_init_done) if (my_init_done)
my_end(0); my_end(0);
#ifdef HAVE_SSL
ma_pvio_ssl_end();
#endif
mysql_client_init= 0; mysql_client_init= 0;
my_init_done= 0; my_init_done= 0;
} }
@@ -3571,7 +3608,7 @@ static my_socket mariadb_get_socket(MYSQL *mysql)
return sock; return sock;
} }
int STDCALL mariadb_flush_multi_command(MYSQL *mysql) int mariadb_flush_multi_command(MYSQL *mysql)
{ {
int is_multi= 0; int is_multi= 0;
int rc; int rc;
@@ -3625,6 +3662,21 @@ my_bool STDCALL mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *
case MARIADB_NET_BUFFER_LENGTH: case MARIADB_NET_BUFFER_LENGTH:
*((size_t *)arg)= (size_t)net_buffer_length; *((size_t *)arg)= (size_t)net_buffer_length;
break; break;
case MARIADB_CONNECTION_ERROR_ID:
if (!mysql)
goto error;
*((unsigned int *)arg)= mysql->net.last_errno;
break;
case MARIADB_CONNECTION_ERROR:
if (!mysql)
goto error;
*((char **)arg)= mysql->net.last_error;
break;
case MARIADB_CONNECTION_SQLSTATE:
if (!mysql)
goto error;
*((char **)arg)= mysql->net.sqlstate;
break;
case MARIADB_CONNECTION_SSL_VERSION: case MARIADB_CONNECTION_SSL_VERSION:
#ifdef HAVE_SSL #ifdef HAVE_SSL
if (mysql && mysql->net.pvio && mysql->net.pvio->cssl) if (mysql && mysql->net.pvio && mysql->net.pvio->cssl)
@@ -3649,6 +3701,19 @@ my_bool STDCALL mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *
#endif #endif
goto error; goto error;
break; break;
case MARIADB_SSL_LIBRARY:
#ifdef HAVE_SSL
#ifdef HAVE_GNUTLS
*((char **)arg)= "GNUTLS";
#elif HAVE_OPENSSL
*((char **)arg)= "OPENSSL";
#elif HAVE_SCHANNEL
*((char **)arg)= "SCHANNEL";
#endif
#else
*((char **)arg)= "OFF";
#endif
break;
case MARIADB_CLIENT_VERSION: case MARIADB_CLIENT_VERSION:
*((char **)arg)= MYSQL_CLIENT_VERSION; *((char **)arg)= MYSQL_CLIENT_VERSION;
break; break;
@@ -3679,7 +3744,7 @@ my_bool STDCALL mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *
else else
goto error; goto error;
break; break;
case MARIADB_CHARSET_INFO: case MARIADB_CONNECTION_CHARSET_INFO:
if (mysql) if (mysql)
mariadb_get_charset_info(mysql, (MY_CHARSET_INFO *)arg); mariadb_get_charset_info(mysql, (MY_CHARSET_INFO *)arg);
else else
@@ -3750,7 +3815,7 @@ my_bool STDCALL mariadb_get_infov(MYSQL *mysql, enum mariadb_value value, void *
goto error; goto error;
break; break;
case MARIADB_CONNECTION_PVIO_TYPE: case MARIADB_CONNECTION_PVIO_TYPE:
if (mysql && !mysql->net.pvio) if (mysql && mysql->net.pvio)
*((unsigned int *)arg)= (unsigned int)mysql->net.pvio->type; *((unsigned int *)arg)= (unsigned int)mysql->net.pvio->type;
else else
goto error; goto error;

View File

@@ -70,6 +70,7 @@ MARIADB_PVIO *ma_pvio_init(MA_PVIO_CINFO *cinfo)
* Currently we support the following pvio types: * Currently we support the following pvio types:
* pvio_socket * pvio_socket
* pvio_namedpipe * pvio_namedpipe
* pvio_sharedmed
*/ */
char *pvio_plugins[] = {"pvio_socket", "pvio_npipe", "pvio_shmem"}; char *pvio_plugins[] = {"pvio_socket", "pvio_npipe", "pvio_shmem"};
int type; int type;
@@ -488,8 +489,8 @@ my_bool ma_pvio_is_blocking(MARIADB_PVIO *pvio)
my_bool ma_pvio_has_data(MARIADB_PVIO *pvio, ssize_t *data_len) my_bool ma_pvio_has_data(MARIADB_PVIO *pvio, ssize_t *data_len)
{ {
/* check if we still have unread data in cache */ /* check if we still have unread data in cache */
if (pvio->cache) if (pvio && pvio->cache)
if (pvio->cache_pos > pvio->cache) if (pvio->cache_pos > pvio->cache)
return test(pvio->cache_pos - pvio->cache); return test(pvio->cache_pos - pvio->cache);
if (pvio && pvio->methods->has_data) if (pvio && pvio->methods->has_data)
return pvio->methods->has_data(pvio, data_len); return pvio->methods->has_data(pvio, data_len);

View File

@@ -78,7 +78,11 @@ MARIADB_SSL *ma_pvio_ssl_init(MYSQL *mysql)
my_bool ma_pvio_ssl_connect(MARIADB_SSL *cssl) my_bool ma_pvio_ssl_connect(MARIADB_SSL *cssl)
{ {
return ma_ssl_connect(cssl); my_bool rc;
if ((rc= ma_ssl_connect(cssl)))
ma_ssl_close(cssl);
return rc;
} }
size_t ma_pvio_ssl_read(MARIADB_SSL *cssl, const uchar* buffer, size_t length) size_t ma_pvio_ssl_read(MARIADB_SSL *cssl, const uchar* buffer, size_t length)
@@ -106,6 +110,11 @@ const char *ma_pvio_ssl_cipher(MARIADB_SSL *cssl)
return ma_ssl_get_cipher(cssl); return ma_ssl_get_cipher(cssl);
} }
void ma_pvio_ssl_end()
{
return ma_ssl_end();
}
my_bool ma_pvio_ssl_get_protocol_version(MARIADB_SSL *cssl, struct st_ssl_version *version) my_bool ma_pvio_ssl_get_protocol_version(MARIADB_SSL *cssl, struct st_ssl_version *version)
{ {
return ma_ssl_get_protocol_version(cssl, version); return ma_ssl_get_protocol_version(cssl, version);

View File

@@ -20,6 +20,7 @@
swapcontext(). swapcontext().
*/ */
#include "my_global.h"
#include "mysys_priv.h" #include "mysys_priv.h"
#include "m_string.h" #include "m_string.h"
#include "my_context.h" #include "my_context.h"

View File

@@ -1227,6 +1227,9 @@ int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, size_t lengt
int rc= 1; int rc= 1;
DBUG_ENTER("mysql_stmt_prepare"); DBUG_ENTER("mysql_stmt_prepare");
if (length == -1)
length= strlen(query);
if (!stmt->mysql) if (!stmt->mysql)
{ {
SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0); SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
@@ -1374,8 +1377,12 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
stmt->result_cursor= stmt->result.data; stmt->result_cursor= stmt->result.data;
stmt->fetch_row_func= stmt_buffered_fetch; stmt->fetch_row_func= stmt_buffered_fetch;
stmt->mysql->status= MYSQL_STATUS_READY; stmt->mysql->status= MYSQL_STATUS_READY;
stmt->state= MYSQL_STMT_USE_OR_STORE_CALLED;
if (!stmt->result.rows)
stmt->state= MYSQL_STMT_FETCH_DONE;
else
stmt->state= MYSQL_STMT_USE_OR_STORE_CALLED;
/* set affected rows: see bug 2247 */ /* set affected rows: see bug 2247 */
stmt->upsert_status.affected_rows= stmt->result.rows; stmt->upsert_status.affected_rows= stmt->result.rows;
@@ -1640,6 +1647,7 @@ static my_bool madb_reset_stmt(MYSQL_STMT *stmt, unsigned int flags)
stmt->result.rows= 0; stmt->result.rows= 0;
stmt->result_cursor= NULL; stmt->result_cursor= NULL;
stmt->mysql->status= MYSQL_STATUS_READY; stmt->mysql->status= MYSQL_STATUS_READY;
stmt->state= MYSQL_STMT_FETCH_DONE;
} }
/* if there is a pending result set, we will flush it */ /* if there is a pending result set, we will flush it */

View File

@@ -195,9 +195,10 @@ static my_bool net_realloc(NET *net, my_bool is_multi, size_t length)
/* Remove unwanted characters from connection */ /* Remove unwanted characters from connection */
void net_clear(NET *net) void net_clear(NET *net)
{ {
size_t len; // size_t len;
DBUG_ENTER("net_clear"); DBUG_ENTER("net_clear");
ma_pvio_has_data(net->pvio, &len); /* if (net->pvio)
ma_pvio_has_data(net->pvio, &len); */
net->compress_pkt_nr= net->pkt_nr=0; /* Ready for new command */ net->compress_pkt_nr= net->pkt_nr=0; /* Ready for new command */
net->write_pos=net->buff; net->write_pos=net->buff;
if (net->mbuff) if (net->mbuff)

View File

@@ -35,6 +35,7 @@ pthread_mutex_t LOCK_gnutls_config;
static gnutls_certificate_credentials_t GNUTLS_xcred; static gnutls_certificate_credentials_t GNUTLS_xcred;
extern my_bool ma_ssl_initialized; extern my_bool ma_ssl_initialized;
extern unsigned int mariadb_deinitialize_ssl;
static int my_verify_callback(gnutls_session_t ssl); static int my_verify_callback(gnutls_session_t ssl);
@@ -137,7 +138,8 @@ void ma_ssl_end()
gnutls_certificate_free_crls(GNUTLS_xcred); gnutls_certificate_free_crls(GNUTLS_xcred);
gnutls_certificate_free_ca_names(GNUTLS_xcred); gnutls_certificate_free_ca_names(GNUTLS_xcred);
gnutls_certificate_free_credentials(GNUTLS_xcred); gnutls_certificate_free_credentials(GNUTLS_xcred);
gnutls_global_deinit(); if (mariadb_deinitialize_ssl)
gnutls_global_deinit();
ma_ssl_initialized= FALSE; ma_ssl_initialized= FALSE;
} }
pthread_mutex_unlock(&LOCK_gnutls_config); pthread_mutex_unlock(&LOCK_gnutls_config);
@@ -204,7 +206,7 @@ void *ma_ssl_init(MYSQL *mysql)
goto error; goto error;
gnutls_session_set_ptr(ssl, (void *)mysql); gnutls_session_set_ptr(ssl, (void *)mysql);
ssl_error= gnutls_priority_set_direct(ssl, "NORMAL:-DHE-RSA", &err); ssl_error= gnutls_priority_set_direct(ssl, "NORMAL", &err);
if (ssl_error < 0) if (ssl_error < 0)
goto error; goto error;

View File

@@ -41,6 +41,7 @@
#include <my_pthread.h> #include <my_pthread.h>
extern my_bool ma_ssl_initialized; extern my_bool ma_ssl_initialized;
extern unsigned int mariadb_deinitialize_ssl;
static SSL_CTX *SSL_context= NULL; static SSL_CTX *SSL_context= NULL;
#define MAX_SSL_ERR_LEN 100 #define MAX_SSL_ERR_LEN 100
@@ -226,14 +227,16 @@ void ma_ssl_end()
SSL_CTX_free(SSL_context); SSL_CTX_free(SSL_context);
SSL_context= NULL; SSL_context= NULL;
} }
ERR_remove_state(0); if (mariadb_deinitialize_ssl)
EVP_cleanup(); {
CRYPTO_cleanup_all_ex_data(); ERR_remove_state(0);
ERR_free_strings(); EVP_cleanup();
//ENGINE_cleanup(); CRYPTO_cleanup_all_ex_data();
CONF_modules_free(); ERR_free_strings();
CONF_modules_unload(1); CONF_modules_free();
sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); CONF_modules_unload(1);
sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
}
ma_ssl_initialized= FALSE; ma_ssl_initialized= FALSE;
} }
pthread_mutex_unlock(&LOCK_openssl_config); pthread_mutex_unlock(&LOCK_openssl_config);
@@ -293,7 +296,12 @@ static int ma_ssl_set_certs(MYSQL *mysql)
if (keyfile && keyfile[0]) if (keyfile && keyfile[0])
{ {
if (SSL_CTX_use_PrivateKey_file(SSL_context, keyfile, SSL_FILETYPE_PEM) != 1) if (SSL_CTX_use_PrivateKey_file(SSL_context, keyfile, SSL_FILETYPE_PEM) != 1)
goto error; {
unsigned long err= ERR_peek_error();
if (!(ERR_GET_LIB(err) == ERR_LIB_X509 &&
ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE))
goto error;
}
} }
if (OPT_HAS_EXT_VAL(mysql, ssl_pw)) if (OPT_HAS_EXT_VAL(mysql, ssl_pw))
{ {

View File

@@ -310,7 +310,6 @@ my_bool ma_ssl_connect(MARIADB_SSL *cssl)
return 0; return 0;
end: end:
/* todo: cleanup */
if (pRemoteCertContext) if (pRemoteCertContext)
CertFreeCertificateContext(pRemoteCertContext); CertFreeCertificateContext(pRemoteCertContext);
if (rc && sctx->IoBufferSize) if (rc && sctx->IoBufferSize)
@@ -322,6 +321,9 @@ end:
CertFreeCertificateContext(sctx->client_cert_ctx); CertFreeCertificateContext(sctx->client_cert_ctx);
if (sctx->client_crl_ctx) if (sctx->client_crl_ctx)
CertFreeCRLContext(sctx->client_crl_ctx); CertFreeCRLContext(sctx->client_crl_ctx);
sctx->client_ca_ctx= 0;
sctx->client_cert_ctx= 0;
sctx->client_crl_ctx= 0;
return 1; return 1;
} }

View File

@@ -1,27 +1,33 @@
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
# Figure out additional libraries for use with # Figure out additional libraries for use with
FOREACH (dep ${libmariadb_LIB_DEPENDS}) FUNCTION(GET_LIB_NAME LIB_NAME LIB_OUT)
STRING(REGEX MATCH "^-l.*$" out "${dep}") STRING(FIND ${LIB_NAME} ".so" IS_SO)
IF(out) IF(NOT ${IS_SO} STREQUAL "-1")
SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} ${dep}") GET_FILENAME_COMPONENT(LIB_FILE ${LIB_NAME} NAME_WE)
ENDIF(out) ELSE()
ENDFOREACH(dep) SET(LIB_FILE ${LIB_NAME})
ENDIF()
SET(LIB_FILE "-l${LIB_FILE}")
STRING(REPLACE "-llib" "-l" LIB_FILE ${LIB_FILE})
SET(${LIB_OUT} ${LIB_FILE} PARENT_SCOPE)
ENDFUNCTION()
LIST(LENGTH SYSTEM_LIBS rllength)
IF(${rllength} GREATER 0)
LIST(REMOVE_DUPLICATES SYSTEM_LIBS)
ENDIF()
FOREACH (LIB_NAME ${SYSTEM_LIBS})
GET_LIB_NAME(${LIB_NAME} LIB_OUT)
SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} ${LIB_OUT}")
ENDFOREACH()
IF(UNIX) IF(UNIX)
IF(OPENSSL_LIBRARIES)
SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} -lssl")
ENDIF()
IF(ICONV_EXTERNAL) IF(ICONV_EXTERNAL)
SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} ${ICONV_LIBRARIES}") SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} ${ICONV_LIBRARIES}")
ENDIF() ENDIF()
FOREACH(lib ${EXTRA_LIBS})
SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} -l${lib}")
ENDFOREACH()
IF(WITH_SQLITE)
SET(extra_dynamic_LDFLAGS "${extra_dynamic_LDFLAGS} -lsqlite")
ENDIF()
ENDIF(UNIX) ENDIF(UNIX)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/mariadb_config.c.in CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/mariadb_config.c.in

View File

@@ -1,4 +1,5 @@
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/plugins/auth)
INCLUDE(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake) INCLUDE(${CMAKE_SOURCE_DIR}/cmake/install_plugins.cmake)
IF(WITH_SIGNCODE) IF(WITH_SIGNCODE)
@@ -64,3 +65,36 @@ IF(AUTH_CLEARTEXT_PLUGIN_TYPE MATCHES "DYNAMIC")
INSTALL_PLUGIN(mysql_clear_password ${CMAKE_BINARY_DIR}/plugins/auth) INSTALL_PLUGIN(mysql_clear_password ${CMAKE_BINARY_DIR}/plugins/auth)
SIGN_TARGET(mysql_clear_password) SIGN_TARGET(mysql_clear_password)
ENDIF() ENDIF()
# SSPI/GSSAPI plugin
IF(WIN32)
SET(USE_SSPI 1)
ENDIF()
MESSAGE(STATUS "GSSAPI: ${AUTH_GSSAPI_PLUGIN_TYPE}")
IF(${AUTH_GSSAPI_PLUGIN_TYPE} MATCHES "DYNAMIC")
IF(WIN32)
SET_VERSION_INFO("TARGET:auth_gssapi_client"
"FILE_TYPE:VFT_DLL"
"SOURCE_FILE:plugins/auth/auth_gssapi_client.c"
"ORIGINAL_FILE_NAME:auth_gssapi_client.dll"
"FILE_DESCRIPTION:Authentication plugin")
ADD_DEFINITIONS(-DHAVE_AUTH_GSSAPI_DYNAMIC=1)
SET(GSSAPI_SOURCES auth_gssapi_client.c sspi_client.c sspi_errmsg.c ${CMAKE_SOURCE_DIR}/plugins/plugin.def ${gssapi_RC})
ELSE()
IF(GSSAPI_FOUND)
SET(GSSAPI_SOURCES auth_gssapi_client.c gssapi_client.c gssapi_errmsg.c)
ENDIF()
ENDIF()
IF(GSSAPI_FOUND OR WIN32)
ADD_LIBRARY(auth_gssapi_client SHARED ${GSSAPI_SOURCES})
IF(WIN32)
TARGET_LINK_LIBRARIES(auth_gssapi_client secur32.lib)
ELSE()
TARGET_LINK_LIBRARIES(auth_gssapi_client ${GSSAPI_LIBS})
ENDIF()
SET_TARGET_PROPERTIES(auth_gssapi_client PROPERTIES PREFIX "")
INSTALL_PLUGIN(auth_gssapi_client ${CMAKE_BINARY_DIR}/plugins/auth)
SIGN_TARGET(auth_gssapi_client)
ENDIF()
ENDIF()

View File

@@ -0,0 +1,119 @@
/* Copyright (c) 2015-2016, Shuang Qiu, Robbie Harwood,
Vladislav Vaintroub & MariaDB Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/**
@file
GSSAPI authentication plugin, client side
*/
#include <string.h>
#include <stdarg.h>
#include <my_global.h>
#include <mysql.h>
#include <mysqld_error.h>
#include <mysql/client_plugin.h>
#include <mysql.h>
#include <stdio.h>
#include "common.h"
extern int auth_client(char *principal_name,
char *mech,
MYSQL *mysql,
MYSQL_PLUGIN_VIO *vio);
static void parse_server_packet(char *packet, size_t packet_len, char *spn, char *mech)
{
size_t spn_len;
spn_len = strnlen(packet, packet_len);
strncpy(spn, packet, PRINCIPAL_NAME_MAX);
if (spn_len == packet_len - 1)
{
/* Mechanism not included into packet */
*mech = 0;
}
else
{
strncpy(mech, packet + spn_len + 1, MECH_NAME_MAX);
}
}
/**
Set client error message.
*/
void log_client_error(MYSQL *mysql, const char *format, ...)
{
NET *net= &mysql->net;
va_list args;
net->last_errno= ER_UNKNOWN_ERROR;
va_start(args, format);
vsnprintf(net->last_error, sizeof(net->last_error) - 1,
format, args);
va_end(args);
memcpy(net->sqlstate, "HY000", sizeof(net->sqlstate));
}
/**
The main client function of the GSSAPI plugin.
*/
static int gssapi_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
{
int packet_len;
unsigned char *packet;
char spn[PRINCIPAL_NAME_MAX + 1];
char mech[MECH_NAME_MAX + 1];
/* read from server for service principal name */
packet_len= vio->read_packet(vio, &packet);
if (packet_len < 0)
{
return CR_ERROR;
}
parse_server_packet((char *)packet, (size_t)packet_len, spn, mech);
return auth_client(spn, mech, mysql, vio);
}
/* register client plugin */
#ifndef HAVE_AUTH_GSSAPI_DYNAMIC
struct st_mysql_client_plugin_AUTHENTICATION auth_gssapi_plugin=
#else
struct st_mysql_client_plugin_AUTHENTICATION _mysql_client_plugin_declaration_ =
#endif
{
MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
"auth_gssapi_client",
"Shuang Qiu, Robbie Harwood, Vladislav Vaintroub, Georg Richter",
"GSSAPI/SSPI based authentication",
{0, 1, 0},
"BSD",
NULL,
NULL,
gssapi_auth_client
};

4
plugins/auth/common.h Normal file
View File

@@ -0,0 +1,4 @@
/** Maximal length of the target name */
#define PRINCIPAL_NAME_MAX 256
/** Maximal length of the mech string */
#define MECH_NAME_MAX 30

View File

@@ -0,0 +1,127 @@
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
Vladislav Vaintroub & MariaDB Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <gssapi/gssapi.h>
#include <string.h>
#include <stdio.h>
#include <mysql/plugin_auth.h>
#include <mysqld_error.h>
#include <mysql.h>
#include "gssapi_errmsg.h"
extern void log_client_error(MYSQL *mysql,const char *fmt,...);
/* This sends the error to the client */
static void log_error(MYSQL *mysql, OM_uint32 major, OM_uint32 minor, const char *msg)
{
if (GSS_ERROR(major))
{
char sysmsg[1024];
gssapi_errmsg(major, minor, sysmsg, sizeof(sysmsg));
log_client_error(mysql,
"Client GSSAPI error (major %u, minor %u) : %s - %s",
major, minor, msg, sysmsg);
}
else
{
log_client_error(mysql, "Client GSSAPI error : %s", msg);
}
}
int auth_client(char *principal_name, char *mech, MYSQL *mysql, MYSQL_PLUGIN_VIO *vio)
{
int ret= CR_ERROR;
OM_uint32 major= 0, minor= 0;
gss_ctx_id_t ctxt= GSS_C_NO_CONTEXT;
gss_name_t service_name= GSS_C_NO_NAME;
if (principal_name && principal_name[0])
{
/* import principal from plain text */
gss_buffer_desc principal_name_buf;
principal_name_buf.length= strlen(principal_name);
principal_name_buf.value= (void *) principal_name;
major= gss_import_name(&minor, &principal_name_buf, GSS_C_NT_USER_NAME, &service_name);
if (GSS_ERROR(major))
{
log_error(mysql, major, minor, "gss_import_name");
return CR_ERROR;
}
}
gss_buffer_desc input= {0,0};
do
{
gss_buffer_desc output= {0,0};
major= gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &ctxt, service_name,
GSS_C_NO_OID, 0, 0, GSS_C_NO_CHANNEL_BINDINGS,
&input, NULL, &output, NULL, NULL);
if (output.length)
{
/* send credential */
if(vio->write_packet(vio, (unsigned char *)output.value, output.length))
{
/* Server error packet contains detailed message. */
ret= CR_OK_HANDSHAKE_COMPLETE;
gss_release_buffer (&minor, &output);
goto cleanup;
}
}
gss_release_buffer (&minor, &output);
if (GSS_ERROR(major))
{
log_error(mysql, major, minor,"gss_init_sec_context");
goto cleanup;
}
if (major & GSS_S_CONTINUE_NEEDED)
{
int len= vio->read_packet(vio, (unsigned char **) &input.value);
if (len <= 0)
{
/* Server error packet contains detailed message. */
ret= CR_OK_HANDSHAKE_COMPLETE;
goto cleanup;
}
input.length= len;
}
} while (major & GSS_S_CONTINUE_NEEDED);
ret= CR_OK;
cleanup:
if (service_name != GSS_C_NO_NAME)
gss_release_name(&minor, &service_name);
if (ctxt != GSS_C_NO_CONTEXT)
gss_delete_sec_context(&minor, &ctxt, GSS_C_NO_BUFFER);
return ret;
}

View File

@@ -0,0 +1,75 @@
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
Vladislav Vaintroub & MariaDB Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <gssapi.h>
#include <string.h>
void gssapi_errmsg(OM_uint32 major, OM_uint32 minor, char *buf, size_t size)
{
OM_uint32 message_context;
OM_uint32 status_code;
OM_uint32 maj_status;
OM_uint32 min_status;
gss_buffer_desc status_string;
char *p= buf;
char *end= buf + size - 1;
int types[] = {GSS_C_GSS_CODE,GSS_C_MECH_CODE};
for(int i= 0; i < 2;i++)
{
message_context= 0;
status_code= types[i] == GSS_C_GSS_CODE?major:minor;
if(!status_code)
continue;
do
{
maj_status = gss_display_status(
&min_status,
status_code,
types[i],
GSS_C_NO_OID,
&message_context,
&status_string);
if(maj_status)
break;
if(p + status_string.length + 2 < end)
{
memcpy(p,status_string.value, status_string.length);
p += status_string.length;
*p++ = '.';
*p++ = ' ';
}
gss_release_buffer(&min_status, &status_string);
}
while (message_context != 0);
}
*p= 0;
}

View File

@@ -0,0 +1,29 @@
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
Vladislav Vaintroub & MariaDB Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
extern void gssapi_errmsg(OM_uint32 major, OM_uint32 minor, char *buf, size_t size);

View File

@@ -0,0 +1,51 @@
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
Vladislav Vaintroub & MariaDB Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/* Plugin variables*/
#include <mysql/plugin_auth.h>
typedef enum
{
PLUGIN_MECH_KERBEROS = 0,
PLUGIN_MECH_SPNEGO = 1,
PLUGIN_MECH_DEFAULT = 2
}PLUGIN_MECH;
extern unsigned long srv_mech;
extern char *srv_principal_name;
extern char *srv_mech_name;
extern char *srv_keytab_path;
/*
Check, with GSSAPI/SSPI username of logged on user.
Depending on use_full_name parameter, compare either full name
(principal name like user@real), or local name (first component)
*/
int plugin_init();
int plugin_deinit();
int auth_server(MYSQL_PLUGIN_VIO *vio, const char *username, size_t username_len, int use_full_name);

183
plugins/auth/sspi_client.c Normal file
View File

@@ -0,0 +1,183 @@
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
Vladislav Vaintroub & MariaDB Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#define SECURITY_WIN32
#include <windows.h>
#include <sspi.h>
#include <SecExt.h>
#include <stdarg.h>
#include <stdio.h>
#include <mysql/plugin_auth.h>
#include <mysql.h>
#include <mysqld_error.h>
#include "sspi_common.h"
extern void log_client_error(MYSQL *mysql, const char *fmt, ...);
static void log_error(MYSQL *mysql, SECURITY_STATUS err, const char *msg)
{
if (err)
{
char buf[1024];
sspi_errmsg(err, buf, sizeof(buf));
log_client_error(mysql, "SSPI client error 0x%x - %s - %s", err, msg, buf);
}
else
{
log_client_error(mysql, "SSPI client error %s", msg);
}
}
/** Client side authentication*/
int auth_client(char *principal_name, char *mech, MYSQL *mysql, MYSQL_PLUGIN_VIO *vio)
{
int ret;
CredHandle cred;
CtxtHandle ctxt;
ULONG attribs = 0;
TimeStamp lifetime;
SECURITY_STATUS sspi_err;
SecBufferDesc inbuf_desc;
SecBuffer inbuf;
SecBufferDesc outbuf_desc;
SecBuffer outbuf;
PBYTE out = NULL;
ret= CR_ERROR;
SecInvalidateHandle(&ctxt);
SecInvalidateHandle(&cred);
if (!mech || strcmp(mech, "Negotiate") != 0)
{
mech= "Kerberos";
}
sspi_err = AcquireCredentialsHandle(
NULL,
mech,
SECPKG_CRED_OUTBOUND,
NULL,
NULL,
NULL,
NULL,
&cred,
&lifetime);
if (SEC_ERROR(sspi_err))
{
log_error(mysql, sspi_err, "AcquireCredentialsHandle");
return CR_ERROR;
}
out = (PBYTE)malloc(SSPI_MAX_TOKEN_SIZE);
if (!out)
{
log_error(mysql, SEC_E_OK, "memory allocation error");
goto cleanup;
}
/* Prepare buffers */
inbuf_desc.ulVersion = SECBUFFER_VERSION;
inbuf_desc.cBuffers = 1;
inbuf_desc.pBuffers = &inbuf;
inbuf.BufferType = SECBUFFER_TOKEN;
inbuf.cbBuffer = 0;
inbuf.pvBuffer = NULL;
outbuf_desc.ulVersion = SECBUFFER_VERSION;
outbuf_desc.cBuffers = 1;
outbuf_desc.pBuffers = &outbuf;
outbuf.BufferType = SECBUFFER_TOKEN;
outbuf.pvBuffer = out;
do
{
outbuf.cbBuffer= SSPI_MAX_TOKEN_SIZE;
sspi_err= InitializeSecurityContext(
&cred,
SecIsValidHandle(&ctxt) ? &ctxt : NULL,
principal_name,
0,
0,
SECURITY_NATIVE_DREP,
inbuf.cbBuffer ? &inbuf_desc : NULL,
0,
&ctxt,
&outbuf_desc,
&attribs,
&lifetime);
if (SEC_ERROR(sspi_err))
{
log_error(mysql, sspi_err, "InitializeSecurityContext");
goto cleanup;
}
if (sspi_err != SEC_E_OK && sspi_err != SEC_I_CONTINUE_NEEDED)
{
log_error(mysql, sspi_err, "Unexpected response from InitializeSecurityContext");
goto cleanup;
}
if (outbuf.cbBuffer)
{
/* send credential to server */
if (vio->write_packet(vio, (unsigned char *)outbuf.pvBuffer, outbuf.cbBuffer))
{
/* Server error packet contains detailed message. */
ret= CR_OK_HANDSHAKE_COMPLETE;
goto cleanup;
}
}
if (sspi_err == SEC_I_CONTINUE_NEEDED)
{
int len= vio->read_packet(vio, (unsigned char **)&inbuf.pvBuffer);
if (len <= 0)
{
/* Server side error is in the last server packet. */
ret= CR_OK_HANDSHAKE_COMPLETE;
goto cleanup;
}
inbuf.cbBuffer= len;
}
} while (sspi_err == SEC_I_CONTINUE_NEEDED);
ret= CR_OK;
cleanup:
if (SecIsValidHandle(&ctxt))
DeleteSecurityContext(&ctxt);
if (SecIsValidHandle(&cred))
FreeCredentialsHandle(&cred);
free(out);
return ret;
}

View File

@@ -0,0 +1,38 @@
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
Vladislav Vaintroub & MariaDB Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#define SECURITY_WIN32
#include <windows.h>
#include <sspi.h>
#include <SecExt.h>
#include <stdarg.h>
#include <stdio.h>
#define SSPI_MAX_TOKEN_SIZE 50000
#define SEC_ERROR(err) (err < 0)
extern void sspi_errmsg(int err, char *buf, size_t size);

150
plugins/auth/sspi_errmsg.c Normal file
View File

@@ -0,0 +1,150 @@
/* Copyright (c) 2015, Shuang Qiu, Robbie Harwood,
Vladislav Vaintroub & MariaDB Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <windows.h>
#include <stdio.h>
#define ERRSYM(x) {x, #x}
static struct {
int error;
const char *sym;
} error_symbols[] =
{
ERRSYM(SEC_E_OK),
ERRSYM(SEC_E_INSUFFICIENT_MEMORY),
ERRSYM(SEC_E_INVALID_HANDLE),
ERRSYM(SEC_E_UNSUPPORTED_FUNCTION),
ERRSYM(SEC_E_TARGET_UNKNOWN),
ERRSYM(SEC_E_INTERNAL_ERROR),
ERRSYM(SEC_E_SECPKG_NOT_FOUND),
ERRSYM(SEC_E_NOT_OWNER),
ERRSYM(SEC_E_CANNOT_INSTALL),
ERRSYM(SEC_E_INVALID_TOKEN),
ERRSYM(SEC_E_CANNOT_PACK),
ERRSYM(SEC_E_QOP_NOT_SUPPORTED),
ERRSYM(SEC_E_NO_IMPERSONATION),
ERRSYM(SEC_E_LOGON_DENIED),
ERRSYM(SEC_E_UNKNOWN_CREDENTIALS),
ERRSYM(SEC_E_NO_CREDENTIALS),
ERRSYM(SEC_E_MESSAGE_ALTERED),
ERRSYM(SEC_E_OUT_OF_SEQUENCE),
ERRSYM(SEC_E_NO_AUTHENTICATING_AUTHORITY),
ERRSYM(SEC_E_BAD_PKGID),
ERRSYM(SEC_E_CONTEXT_EXPIRED),
ERRSYM(SEC_E_INCOMPLETE_MESSAGE),
ERRSYM(SEC_E_INCOMPLETE_CREDENTIALS),
ERRSYM(SEC_E_BUFFER_TOO_SMALL),
ERRSYM(SEC_E_WRONG_PRINCIPAL),
ERRSYM(SEC_E_TIME_SKEW),
ERRSYM(SEC_E_UNTRUSTED_ROOT),
ERRSYM(SEC_E_ILLEGAL_MESSAGE),
ERRSYM(SEC_E_CERT_UNKNOWN),
ERRSYM(SEC_E_CERT_EXPIRED),
ERRSYM(SEC_E_ENCRYPT_FAILURE),
ERRSYM(SEC_E_DECRYPT_FAILURE),
ERRSYM(SEC_E_ALGORITHM_MISMATCH),
ERRSYM(SEC_E_SECURITY_QOS_FAILED),
ERRSYM(SEC_E_UNFINISHED_CONTEXT_DELETED),
ERRSYM(SEC_E_NO_TGT_REPLY),
ERRSYM(SEC_E_NO_IP_ADDRESSES),
ERRSYM(SEC_E_WRONG_CREDENTIAL_HANDLE),
ERRSYM(SEC_E_CRYPTO_SYSTEM_INVALID),
ERRSYM(SEC_E_MAX_REFERRALS_EXCEEDED),
ERRSYM(SEC_E_MUST_BE_KDC),
ERRSYM(SEC_E_STRONG_CRYPTO_NOT_SUPPORTED),
ERRSYM(SEC_E_TOO_MANY_PRINCIPALS),
ERRSYM(SEC_E_NO_PA_DATA),
ERRSYM(SEC_E_PKINIT_NAME_MISMATCH),
ERRSYM(SEC_E_SMARTCARD_LOGON_REQUIRED),
ERRSYM(SEC_E_SHUTDOWN_IN_PROGRESS),
ERRSYM(SEC_E_KDC_INVALID_REQUEST),
ERRSYM(SEC_E_KDC_UNABLE_TO_REFER),
ERRSYM(SEC_E_KDC_UNKNOWN_ETYPE),
ERRSYM(SEC_E_UNSUPPORTED_PREAUTH),
ERRSYM(SEC_E_DELEGATION_REQUIRED),
ERRSYM(SEC_E_BAD_BINDINGS),
ERRSYM(SEC_E_MULTIPLE_ACCOUNTS),
ERRSYM(SEC_E_NO_KERB_KEY),
ERRSYM(SEC_E_CERT_WRONG_USAGE),
ERRSYM(SEC_E_DOWNGRADE_DETECTED),
ERRSYM(SEC_E_SMARTCARD_CERT_REVOKED),
ERRSYM(SEC_E_ISSUING_CA_UNTRUSTED),
ERRSYM(SEC_E_REVOCATION_OFFLINE_C),
ERRSYM(SEC_E_PKINIT_CLIENT_FAILURE),
ERRSYM(SEC_E_SMARTCARD_CERT_EXPIRED),
ERRSYM(SEC_E_NO_S4U_PROT_SUPPORT),
ERRSYM(SEC_E_CROSSREALM_DELEGATION_FAILURE),
ERRSYM(SEC_E_REVOCATION_OFFLINE_KDC),
ERRSYM(SEC_E_ISSUING_CA_UNTRUSTED_KDC),
ERRSYM(SEC_E_KDC_CERT_EXPIRED),
ERRSYM(SEC_E_KDC_CERT_REVOKED),
ERRSYM(SEC_E_INVALID_PARAMETER),
ERRSYM(SEC_E_DELEGATION_POLICY),
ERRSYM(SEC_E_POLICY_NLTM_ONLY),
ERRSYM(SEC_E_NO_CONTEXT),
ERRSYM(SEC_E_PKU2U_CERT_FAILURE),
ERRSYM(SEC_E_MUTUAL_AUTH_FAILED),
ERRSYM(SEC_E_NO_SPM),
ERRSYM(SEC_E_NOT_SUPPORTED),
{0,0}
};
void sspi_errmsg(int err, char *buf, size_t size)
{
buf[size - 1] = 0;
size_t len;
for (size_t i= 0; error_symbols[i].sym; i++)
{
if (error_symbols[i].error == err)
{
size_t len= strlen(error_symbols[i].sym);
if (len + 2 < size)
{
memcpy(buf, error_symbols[i].sym, len);
buf[len]= ' ';
buf += len + 1;
size-= len + 1;
}
break;
}
}
len = FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
err, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
buf, size, NULL);
if(len > 0)
{
/* Trim trailing \n\r*/
char *p;
for(p= buf + len;p > buf && (*p == '\n' || *p=='\r' || *p == 0);p--)
*p= 0;
}
}

View File

@@ -3,6 +3,7 @@ IF(WIN32)
ENDIF() ENDIF()
SET(CMAKE_SHARED_LIBRARY_PREFIX "") SET(CMAKE_SHARED_LIBRARY_PREFIX "")
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC") IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC")
IF(WIN32) IF(WIN32)
@@ -20,7 +21,7 @@ IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC")
SET(INSTALL_LIBS replication) SET(INSTALL_LIBS replication)
ENDIF() ENDIF()
IF(REPLICATION_PLUGIN_TYPE MATCHES "DYNAMIC") IF(AURORA_PLUGIN_TYPE MATCHES "DYNAMIC")
IF(WIN32) IF(WIN32)
SET_VERSION_INFO("TARGET:aurora" SET_VERSION_INFO("TARGET:aurora"
"FILE_TYPE:VFT_DLL" "FILE_TYPE:VFT_DLL"

View File

@@ -45,7 +45,6 @@ MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const ch
void aurora_close(MYSQL *mysql); void aurora_close(MYSQL *mysql);
int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *arg, int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
size_t length, my_bool skipp_check, void *opt_arg); size_t length, my_bool skipp_check, void *opt_arg);
int aurora_set_options(MYSQL *msql, enum mysql_option option, void *arg);
my_bool aurora_reconnect(MYSQL *mysql); my_bool aurora_reconnect(MYSQL *mysql);
#define AURORA_MAX_INSTANCES 16 #define AURORA_MAX_INSTANCES 16
@@ -55,11 +54,6 @@ my_bool aurora_reconnect(MYSQL *mysql);
#define AURORA_REPLICA 1 #define AURORA_REPLICA 1
#define AURORA_UNAVAILABLE 2 #define AURORA_UNAVAILABLE 2
#define ENABLE_AURORA(mysql)\
(mysql)->net.conn_hdlr->active= 1;
#define DISABLE_AURORA(mysql)\
(mysql)->net.conn_hdlr->active= 0;
#ifndef HAVE_AURORA_DYNAMIC #ifndef HAVE_AURORA_DYNAMIC
MARIADB_CONNECTION_PLUGIN connection_aurora_plugin = MARIADB_CONNECTION_PLUGIN connection_aurora_plugin =
#else #else
@@ -77,7 +71,7 @@ MARIADB_CONNECTION_PLUGIN _mysql_client_plugin_declaration_ =
NULL, NULL,
aurora_connect, aurora_connect,
aurora_close, aurora_close,
aurora_set_options, NULL,
aurora_command, aurora_command,
aurora_reconnect aurora_reconnect
}; };
@@ -92,16 +86,14 @@ typedef struct st_aurora_instance {
} AURORA_INSTANCE; } AURORA_INSTANCE;
typedef struct st_conn_aurora { typedef struct st_conn_aurora {
MARIADB_PVIO *pvio[2]; MYSQL *mysql[2],
MYSQL *mysql[2]; save_mysql;
my_bool active[2];
char *url; char *url;
unsigned int num_instances; unsigned int num_instances;
AURORA_INSTANCE instance[AURORA_MAX_INSTANCES]; AURORA_INSTANCE instance[AURORA_MAX_INSTANCES];
char *username, *password, *database; char *username, *password, *database;
unsigned int port; unsigned int port;
unsigned long client_flag; unsigned long client_flag;
unsigned int last_instance_type; /* Primary or Replica */
char primary_id[100]; char primary_id[100];
} AURORA; } AURORA;
@@ -118,20 +110,13 @@ my_bool aurora_switch_connection(MYSQL *mysql, AURORA *aurora, int type)
case AURORA_REPLICA: case AURORA_REPLICA:
if (aurora->mysql[AURORA_REPLICA]) if (aurora->mysql[AURORA_REPLICA])
{ {
mysql->net.pvio= aurora->pvio[AURORA_REPLICA]; *mysql= *aurora->mysql[AURORA_REPLICA];
aurora->pvio[AURORA_REPLICA]->mysql= mysql;
mysql->thread_id= aurora->mysql[AURORA_REPLICA]->thread_id;
aurora->last_instance_type= AURORA_REPLICA;
} }
break; break;
case AURORA_PRIMARY: case AURORA_PRIMARY:
if (aurora->mysql[AURORA_PRIMARY]) if (aurora->mysql[AURORA_PRIMARY])
{ {
if (aurora->mysql[AURORA_REPLICA]) *mysql= *aurora->mysql[AURORA_PRIMARY];
aurora->mysql[AURORA_REPLICA]->net.pvio->mysql= aurora->mysql[AURORA_REPLICA];
mysql->net.pvio= aurora->pvio[AURORA_PRIMARY];
mysql->thread_id= aurora->mysql[AURORA_PRIMARY]->thread_id;
aurora->last_instance_type= AURORA_PRIMARY;
} }
break; break;
default: default:
@@ -257,17 +242,23 @@ my_bool aurora_parse_url(const char *url, AURORA *aurora)
*/ */
int aurora_get_instance_type(MYSQL *mysql) int aurora_get_instance_type(MYSQL *mysql)
{ {
int rc; int rc= -1;
MA_CONNECTION_HANDLER *save_hdlr= mysql->net.conn_hdlr;
char *query= "select variable_value from information_schema.global_variables where variable_name='INNODB_READ_ONLY' AND variable_value='OFF'"; char *query= "select variable_value from information_schema.global_variables where variable_name='INNODB_READ_ONLY' AND variable_value='OFF'";
if (!mysql)
return -1;
mysql->net.conn_hdlr= 0;
if (!mariadb_api->mysql_query(mysql, query)) if (!mariadb_api->mysql_query(mysql, query))
{ {
MYSQL_RES *res= mysql_store_result(mysql); MYSQL_RES *res= mariadb_api->mysql_store_result(mysql);
rc= mysql_num_rows(res) ? AURORA_PRIMARY : AURORA_REPLICA; rc= mysql_num_rows(res) ? AURORA_PRIMARY : AURORA_REPLICA;
mysql_free_result(res); mariadb_api->mysql_free_result(res);
return rc;
} }
return -1; mysql->net.conn_hdlr= save_hdlr;
return rc;
} }
/* }}} */ /* }}} */
@@ -287,16 +278,18 @@ int aurora_get_instance_type(MYSQL *mysql)
my_bool aurora_get_primary_id(MYSQL *mysql, AURORA *aurora) my_bool aurora_get_primary_id(MYSQL *mysql, AURORA *aurora)
{ {
my_bool rc= 0; my_bool rc= 0;
MA_CONNECTION_HANDLER *save_hdlr= mysql->net.conn_hdlr;
mysql->net.conn_hdlr= 0;
if (!mariadb_api->mysql_query(mysql, "select server_id from information_schema.replica_host_status " if (!mariadb_api->mysql_query(mysql, "select server_id from information_schema.replica_host_status "
"where session_id = 'MASTER_SESSION_ID'")) "where session_id = 'MASTER_SESSION_ID'"))
{ {
MYSQL_RES *res; MYSQL_RES *res;
MYSQL_ROW row; MYSQL_ROW row;
if ((res= mysql_store_result(mysql))) if ((res= mariadb_api->mysql_store_result(mysql)))
{ {
if ((row= mysql_fetch_row(res))) if ((row= mariadb_api->mysql_fetch_row(res)))
{ {
if (row[0]) if (row[0])
{ {
@@ -304,9 +297,10 @@ my_bool aurora_get_primary_id(MYSQL *mysql, AURORA *aurora)
rc= 1; rc= 1;
} }
} }
mysql_free_result(res); mariadb_api->mysql_free_result(res);
} }
} }
mysql->net.conn_hdlr= save_hdlr;
return rc; return rc;
} }
/* }}} */ /* }}} */
@@ -326,7 +320,7 @@ static unsigned int aurora_get_valid_instances(AURORA *aurora, AURORA_INSTANCE *
{ {
if (aurora->instance[i].type != AURORA_UNAVAILABLE) if (aurora->instance[i].type != AURORA_UNAVAILABLE)
{ {
if (aurora->instance[i].type == AURORA_PRIMARY && aurora->active[AURORA_PRIMARY]) if (aurora->instance[i].type == AURORA_PRIMARY && aurora->mysql[AURORA_PRIMARY])
continue; continue;
instances[valid_instances]= &aurora->instance[i]; instances[valid_instances]= &aurora->instance[i];
valid_instances++; valid_instances++;
@@ -355,14 +349,14 @@ void aurora_refresh_blacklist(AURORA *aurora)
/* {{{ MYSQL *aurora_connect_instance() */ /* {{{ MYSQL *aurora_connect_instance() */
MYSQL *aurora_connect_instance(AURORA *aurora, AURORA_INSTANCE *instance, MYSQL *mysql) MYSQL *aurora_connect_instance(AURORA *aurora, AURORA_INSTANCE *instance, MYSQL *mysql)
{ {
if (!mysql->methods->db_connect(mysql, if (!mariadb_api->mysql_real_connect(mysql,
instance->host, instance->host,
aurora->username, aurora->username,
aurora->password, aurora->password,
aurora->database, aurora->database,
instance->port ? instance->port : aurora->port, instance->port ? instance->port : aurora->port,
NULL, NULL,
aurora->client_flag)) aurora->client_flag | CLIENT_REMEMBER_OPTIONS))
{ {
/* connection not available */ /* connection not available */
instance->blacklisted= time(NULL); instance->blacklisted= time(NULL);
@@ -386,31 +380,21 @@ MYSQL *aurora_connect_instance(AURORA *aurora, AURORA_INSTANCE *instance, MYSQL
return NULL; return NULL;
} }
if (!aurora->primary_id[0]) if (!aurora->primary_id[0])
aurora_get_primary_id(mysql, aurora); if (aurora_get_primary_id(mysql, aurora))
return NULL;
return mysql; return mysql;
} }
/* }}} */ /* }}} */
/* {{{ void aurora_copy_mysql() */ /* {{{ void aurora_close_internal */
void aurora_copy_mysql(MYSQL *from, MYSQL *to) void aurora_close_internal(MYSQL *mysql)
{ {
/* invalidate statements */ if (mysql)
to->methods->invalidate_stmts(to, "aurora connect/reconnect"); {
mysql->net.conn_hdlr= 0;
from->free_me= to->free_me; memset(&mysql->options, 0, sizeof(struct st_mysql_options));
from->reconnect= to->reconnect; mariadb_api->mysql_close(mysql);
from->net.conn_hdlr= to->net.conn_hdlr; }
from->stmts= to->stmts;
to->stmts= NULL;
memset(&to->options, 0, sizeof(to->options));
to->free_me= 0;
to->net.conn_hdlr= 0;
mariadb_api->mysql_close(to);
*to= *from;
to->net.pvio= from->net.pvio;
to->net.pvio->mysql= to;
from->net.pvio= NULL;
} }
/* }}} */ /* }}} */
@@ -420,46 +404,45 @@ my_bool aurora_find_replica(AURORA *aurora)
int valid_instances; int valid_instances;
my_bool replica_found= 0; my_bool replica_found= 0;
AURORA_INSTANCE *instance[AURORA_MAX_INSTANCES]; AURORA_INSTANCE *instance[AURORA_MAX_INSTANCES];
MYSQL mysql; MYSQL *mysql;
if (aurora->num_instances < 2) if (aurora->num_instances < 2)
return 0; return 0;
mariadb_api->mysql_init(&mysql);
mysql.options= aurora->mysql[AURORA_PRIMARY]->options;
/* don't execute init_command on slave */
mysql.net.conn_hdlr= aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr;
valid_instances= aurora_get_valid_instances(aurora, instance); valid_instances= aurora_get_valid_instances(aurora, instance);
while (valid_instances && !replica_found) while (valid_instances && !replica_found)
{ {
int random_pick= rand() % valid_instances; int random_pick= rand() % valid_instances;
if ((aurora_connect_instance(aurora, instance[random_pick], &mysql))) mysql= mariadb_api->mysql_init(NULL);
mysql->options= aurora->save_mysql.options;
/* don't execute init_command on slave */
// mysql->net.conn_hdlr= aurora->save_mysql.net.conn_hdlr;
if ((aurora_connect_instance(aurora, instance[random_pick], mysql)))
{ {
switch (instance[random_pick]->type) { switch (instance[random_pick]->type) {
case AURORA_REPLICA: case AURORA_REPLICA:
if (!aurora->mysql[AURORA_REPLICA]) if (!aurora->mysql[AURORA_REPLICA])
{ aurora->mysql[AURORA_REPLICA]= mysql;
aurora->mysql[AURORA_REPLICA]= mysql_init(NULL);
}
aurora_copy_mysql(&mysql, aurora->mysql[AURORA_REPLICA]);
aurora->active[AURORA_REPLICA]= 1;
return 1; return 1;
break; break;
case AURORA_PRIMARY: case AURORA_PRIMARY:
aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]); if (!aurora->mysql[AURORA_PRIMARY])
aurora->pvio[AURORA_PRIMARY]= aurora->mysql[AURORA_PRIMARY]->net.pvio; aurora->mysql[AURORA_PRIMARY]= mysql;
aurora->active[AURORA_PRIMARY]= 1; else
aurora_close_internal(mysql);
continue; continue;
break; break;
default: default:
mysql_close(&mysql); aurora_close_internal(mysql);
return 0; return 0;
break; break;
} }
} }
else
aurora_close_internal(mysql);
valid_instances= aurora_get_valid_instances(aurora, instance); valid_instances= aurora_get_valid_instances(aurora, instance);
} }
return 0; return 0;
@@ -488,101 +471,79 @@ my_bool aurora_find_primary(AURORA *aurora)
{ {
unsigned int i; unsigned int i;
AURORA_INSTANCE *instance= NULL; AURORA_INSTANCE *instance= NULL;
MYSQL mysql; MYSQL *mysql;
my_bool check_primary= 1; my_bool check_primary= 1;
/* We try to find a primary:
* by looking 1st if a replica connect provided primary_id already
* by walking through instances */
if (!aurora->num_instances) if (!aurora->num_instances)
return 0; return 0;
mariadb_api->mysql_init(&mysql);
mysql.options= aurora->mysql[AURORA_PRIMARY]->options;
mysql.net.conn_hdlr= aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr;
for (i=0; i < aurora->num_instances; i++) for (i=0; i < aurora->num_instances; i++)
{ {
mysql= mariadb_api->mysql_init(NULL);
mysql->options= aurora->save_mysql.options;
if (check_primary && aurora->primary_id[0]) if (check_primary && aurora->primary_id[0])
{ {
if ((instance= aurora_get_primary_id_instance(aurora)) && if ((instance= aurora_get_primary_id_instance(aurora)) &&
aurora_connect_instance(aurora, instance, &mysql) && aurora_connect_instance(aurora, instance, mysql) &&
instance->type == AURORA_PRIMARY) instance->type == AURORA_PRIMARY)
{ {
aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]); aurora->primary_id[0]= 0;
aurora->active[AURORA_PRIMARY]= 1; aurora->mysql[AURORA_PRIMARY]= mysql;
return 1; return 1;
} }
/* primary id connect failed, don't try again */ /* primary id connect failed, don't try again */
aurora->primary_id[0]= 0; aurora->primary_id[0]= 0;
check_primary= 0; check_primary= 0;
} }
if (aurora->instance[i].type != AURORA_UNAVAILABLE) else if (aurora->instance[i].type != AURORA_UNAVAILABLE)
{ {
if (aurora_connect_instance(aurora, &aurora->instance[i], &mysql) if (aurora_connect_instance(aurora, &aurora->instance[i], mysql)
&& aurora->instance[i].type == AURORA_PRIMARY) && aurora->instance[i].type == AURORA_PRIMARY)
{ {
aurora_copy_mysql(&mysql, aurora->mysql[AURORA_PRIMARY]); aurora->mysql[AURORA_PRIMARY]= mysql;
aurora->active[AURORA_PRIMARY]= 1;
return 1; return 1;
} }
} }
aurora_close_internal(mysql);
} }
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ void aurora_close_replica() */
void aurora_close_replica(MYSQL *mysql, AURORA *aurora)
{
if (aurora->mysql[AURORA_REPLICA])
{
aurora->mysql[AURORA_REPLICA]->net.pvio->mysql= aurora->mysql[AURORA_REPLICA];
aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0;
mariadb_api->mysql_close(aurora->mysql[AURORA_REPLICA]);
aurora->pvio[AURORA_REPLICA]= 0;
aurora->mysql[AURORA_REPLICA]= NULL;
}
}
/* }}} */
/* {{{ MYSQL *aurora_connect */ /* {{{ MYSQL *aurora_connect */
MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd,
const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag) const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag)
{ {
AURORA *aurora= NULL; AURORA *aurora= NULL;
MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; MA_CONNECTION_HANDLER *save_hdlr= mysql->net.conn_hdlr;
my_bool is_reconnect= 0;
if (!mariadb_api) if (!mariadb_api)
mariadb_api= mysql->methods->api; mariadb_api= mysql->methods->api;
mariadb_api->mariadb_get_info(mysql, MARIADB_CLIENT_ERRORS, &client_errors); /* we call aurora_connect either from mysql_real_connect or from mysql_reconnect,
* so make sure in case of reconnect we don't allocate aurora twice */
if ((aurora= (AURORA *)hdlr->data)) if (!(aurora= (AURORA *)save_hdlr->data))
{
aurora_refresh_blacklist(aurora);
if (aurora->mysql[aurora->last_instance_type]->net.pvio)
{
SET_CLIENT_ERROR(mysql, CR_ALREADY_CONNECTED, SQLSTATE_UNKNOWN, 0);
return NULL;
}
is_reconnect= 1;
}
else
{ {
if (!(aurora= (AURORA *)calloc(1, sizeof(AURORA)))) if (!(aurora= (AURORA *)calloc(1, sizeof(AURORA))))
{ {
mysql->methods->set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0); mysql->methods->set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
return NULL; return NULL;
} }
aurora->save_mysql= *mysql;
mysql->net.conn_hdlr->data= (void *)aurora; save_hdlr->data= (void *)aurora;
aurora->mysql[AURORA_PRIMARY]= mysql;
if (aurora_parse_url(host, aurora)) if (aurora_parse_url(host, aurora))
{ {
goto error; goto error;
} }
/* store login credentials for connect/reconnect */
if (user) if (user)
aurora->username= strdup(user); aurora->username= strdup(user);
if (passwd) if (passwd)
@@ -591,51 +552,35 @@ MYSQL *aurora_connect(MYSQL *mysql, const char *host, const char *user, const ch
aurora->database= strdup(db); aurora->database= strdup(db);
aurora->port= port; aurora->port= port;
aurora->client_flag= client_flag; aurora->client_flag= client_flag;
aurora->pvio[AURORA_PRIMARY]= aurora->pvio[AURORA_REPLICA]= NULL;
hdlr->data= aurora;
} }
/* we look for replica first:
/* In case of reconnect, close broken connection first */ if it's a primary we don't need to call find_aurora_primary
if (is_reconnect) if it's a replica we can obtain primary_id */
if (!aurora->mysql[AURORA_REPLICA])
{ {
DISABLE_AURORA(mysql); if (!aurora_find_replica(aurora))
switch (aurora->last_instance_type) { aurora->mysql[AURORA_REPLICA]= NULL;
case AURORA_REPLICA:
aurora_close_replica(mysql, aurora);
aurora->pvio[AURORA_REPLICA]= NULL;
break;
case AURORA_PRIMARY:
/* pvio will be closed in mysql_reconnect() */
aurora->pvio[AURORA_PRIMARY]= NULL;
aurora->primary_id[0]= 0;
break;
}
aurora->active[aurora->last_instance_type]= 0;
}
if (!aurora->active[AURORA_REPLICA])
{
if (aurora_find_replica(aurora))
{
aurora->pvio[AURORA_REPLICA]= aurora->mysql[AURORA_REPLICA]->net.pvio;
aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= mysql->net.conn_hdlr;
}
else else
aurora->pvio[AURORA_REPLICA]= NULL; aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= save_hdlr;
} }
if (!aurora->active[AURORA_PRIMARY]) if (!aurora->mysql[AURORA_PRIMARY])
{ {
if (aurora_find_primary(aurora)) if (!aurora_find_primary(aurora))
{ aurora->mysql[AURORA_PRIMARY]= NULL;
aurora->active[AURORA_PRIMARY]= 1; else
aurora->pvio[AURORA_PRIMARY]= aurora->mysql[AURORA_PRIMARY]->net.pvio; aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr= save_hdlr;
}
} }
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); if (!aurora->mysql[AURORA_PRIMARY] && !aurora->mysql[AURORA_REPLICA])
ENABLE_AURORA(mysql); goto error;
if (aurora->mysql[AURORA_PRIMARY])
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
else
aurora_switch_connection(mysql, aurora, AURORA_REPLICA);
mysql->net.conn_hdlr= save_hdlr;
return mysql; return mysql;
error: error:
aurora_close_memory(aurora); aurora_close_memory(aurora);
@@ -647,28 +592,53 @@ error:
my_bool aurora_reconnect(MYSQL *mysql) my_bool aurora_reconnect(MYSQL *mysql)
{ {
AURORA *aurora; AURORA *aurora;
MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; MA_CONNECTION_HANDLER *save_hdlr= mysql->net.conn_hdlr;
my_bool rc= 1; int i;
aurora= (AURORA *)hdlr->data; /* We can't determine if a new primary was promotoed, or if
* line just dropped - we will close both primary and replica
* connection and establish a new connection via
* aurora_connect */
DISABLE_AURORA(mysql); aurora= (AURORA *)save_hdlr->data;
switch (aurora->last_instance_type)
/* removed blacklisted instances */
for (i=0; i < aurora->num_instances; i++)
aurora->instance[i].type= AURORA_UNKNOWN;
if (aurora->mysql[AURORA_PRIMARY]->thread_id == mysql->thread_id)
{ {
case AURORA_REPLICA: /* don't send COM_QUIT */
if (!(rc= mariadb_api->mysql_reconnect(aurora->mysql[aurora->last_instance_type]))) aurora->mysql[AURORA_PRIMARY]->net.pvio= NULL;
aurora_switch_connection(mysql, aurora, AURORA_REPLICA); aurora_close_internal(aurora->mysql[AURORA_PRIMARY]);
break; aurora->mysql[AURORA_PRIMARY]= NULL;
case AURORA_PRIMARY: aurora_close_internal(aurora->mysql[AURORA_REPLICA]);
if (!(rc= mysql_reconnect(aurora->mysql[aurora->last_instance_type]))) aurora->mysql[AURORA_REPLICA]= NULL;
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
break;
default:
/* todo: error message */
break;
} }
ENABLE_AURORA(mysql); else if (aurora->mysql[AURORA_REPLICA]->thread_id == mysql->thread_id)
return rc; {
/* don't send COM_QUIT */
aurora->mysql[AURORA_REPLICA]->net.pvio= NULL;
aurora_close_internal(aurora->mysql[AURORA_REPLICA]);
aurora->mysql[AURORA_REPLICA]= NULL;
aurora_close_internal(aurora->mysql[AURORA_PRIMARY]);
aurora->mysql[AURORA_PRIMARY]= NULL;
}
/* unset connections, so we can connect to primary and replica again */
aurora->mysql[AURORA_PRIMARY]= aurora->mysql[AURORA_REPLICA]= NULL;
if (aurora_connect(mysql, NULL, NULL, NULL, NULL, 0, NULL, 0))
{
if (aurora->mysql[AURORA_PRIMARY])
*mysql= *aurora->mysql[AURORA_PRIMARY];
return 0;
}
if (aurora->mysql[AURORA_REPLICA])
*mysql= *aurora->mysql[AURORA_REPLICA];
else
*mysql= aurora->save_mysql;
return 1;
} }
/* }}} */ /* }}} */
@@ -676,46 +646,34 @@ my_bool aurora_reconnect(MYSQL *mysql)
void aurora_close(MYSQL *mysql) void aurora_close(MYSQL *mysql)
{ {
MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr; MA_CONNECTION_HANDLER *hdlr= mysql->net.conn_hdlr;
AURORA *aurora= (AURORA *)hdlr->data; AURORA *aurora;
int i;
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); if (!hdlr || !hdlr->data)
/* if the connection is not active yet, just return */
if (!aurora->active[1])
return; return;
aurora= (AURORA *)hdlr->data;
*mysql= aurora->save_mysql;
if (aurora->mysql[AURORA_REPLICA]) if (!aurora->mysql[AURORA_PRIMARY] && !aurora->mysql[AURORA_REPLICA])
goto end;
for (i=0; i < 2; i++)
{ {
/* we got options from primary, so don't free it twice */ if (aurora->mysql[i])
memset(&aurora->mysql[AURORA_REPLICA]->options, 0, sizeof(mysql->options)); {
/* connection handler wull be freed in mariadb_api->mysql_close() */ /* Make sure that connection wasn't closed before, e.g. after disconnect */
aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0; if (mysql->thread_id == aurora->mysql[i]->thread_id && !mysql->net.pvio)
aurora->mysql[i]->net.pvio= 0;
mysql_close(aurora->mysql[AURORA_REPLICA]); aurora_close_internal(aurora->mysql[i]);
aurora->mysql[i]= NULL;
}
} }
/* free information */
if (aurora->mysql[AURORA_PRIMARY]) end:
{
/* connection handler wull be freed in mysql_close() */
aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr= 0;
aurora->mysql[AURORA_PRIMARY]->net.pvio= aurora->pvio[AURORA_PRIMARY];
mysql_close(aurora->mysql[AURORA_PRIMARY]);
}
/*
if (aurora->mysql[AURORA_PRIMARY])
{
aurora->mysql[AURORA_PRIMARY]->net.pvio= aurora->pvio[AURORA_PRIMARY];
aurora->mysql[AURORA_PRIMARY]->net.conn_hdlr= 0;
mysql_close(aurora->mysql[AURORA_PRIMARY]);
}
*/
/* free masrwe information */
aurora_close_memory(aurora); aurora_close_memory(aurora);
mysql->net.conn_hdlr= hdlr;
} }
/* }}} */ /* }}} */
@@ -758,7 +716,8 @@ my_bool is_replica_stmt(MYSQL *mysql, const char *buffer)
int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *arg, int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
size_t length, my_bool skipp_check, void *opt_arg) size_t length, my_bool skipp_check, void *opt_arg)
{ {
AURORA *aurora= (AURORA *)mysql->net.conn_hdlr->data; MA_CONNECTION_HANDLER *save_hdlr= mysql->net.conn_hdlr;
AURORA *aurora= (AURORA *)save_hdlr->data;
/* if we don't have slave or slave became unavailable root traffic to master */ /* if we don't have slave or slave became unavailable root traffic to master */
if (!aurora->mysql[AURORA_REPLICA] || !OPT_HAS_EXT_VAL(mysql, read_only)) if (!aurora->mysql[AURORA_REPLICA] || !OPT_HAS_EXT_VAL(mysql, read_only))
@@ -766,54 +725,43 @@ int aurora_command(MYSQL *mysql,enum enum_server_command command, const char *ar
if (command != COM_INIT_DB) if (command != COM_INIT_DB)
{ {
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
return 0; goto end;
} }
} }
switch(command) { switch(command) {
case COM_INIT_DB: case COM_INIT_DB:
/* we need to change default database on primary and replica */ /* we need to change default database on primary and replica */
if (aurora->mysql[AURORA_REPLICA] && aurora->last_instance_type != AURORA_REPLICA) if (aurora->mysql[AURORA_REPLICA] && mysql->thread_id == aurora->mysql[AURORA_PRIMARY]->thread_id)
{ {
aurora_switch_connection(mysql, aurora, AURORA_REPLICA); aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= 0;
DISABLE_AURORA(mysql);
mariadb_api->mysql_select_db(aurora->mysql[AURORA_REPLICA], arg); mariadb_api->mysql_select_db(aurora->mysql[AURORA_REPLICA], arg);
ENABLE_AURORA(mysql); aurora->mysql[AURORA_REPLICA]->net.conn_hdlr= mysql->net.conn_hdlr;
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
} }
break; break;
case COM_QUERY: case COM_QUERY:
case COM_STMT_PREPARE: case COM_STMT_PREPARE:
if (aurora->mysql[AURORA_REPLICA] && aurora->last_instance_type != AURORA_REPLICA) if (aurora->mysql[AURORA_REPLICA])
aurora_switch_connection(mysql, aurora, AURORA_REPLICA); aurora_switch_connection(mysql, aurora, AURORA_REPLICA);
break; break;
case COM_STMT_EXECUTE: case COM_STMT_EXECUTE:
case COM_STMT_FETCH: case COM_STMT_FETCH:
if (aurora->pvio[AURORA_REPLICA]->mysql->stmts && is_replica_stmt(aurora->pvio[AURORA_REPLICA]->mysql, arg)) if (aurora->mysql[AURORA_REPLICA] && aurora->mysql[AURORA_REPLICA]->stmts &&
is_replica_stmt(aurora->mysql[AURORA_REPLICA], arg))
{ {
if (aurora->last_instance_type != AURORA_REPLICA) aurora_switch_connection(mysql, aurora, AURORA_REPLICA);
aurora_switch_connection(mysql, aurora, AURORA_REPLICA);
} }
else else
{ {
if (aurora->last_instance_type != AURORA_PRIMARY) aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
} }
default: default:
aurora_switch_connection(mysql, aurora, AURORA_PRIMARY); aurora_switch_connection(mysql, aurora, AURORA_PRIMARY);
break; break;
} }
end:
mysql->net.conn_hdlr= save_hdlr;
return 0; return 0;
} }
/* }}} */ /* }}} */
/* {{{ int aurora_set_options() */
int aurora_set_options(MYSQL *mysql, enum mysql_option option, void *arg)
{
switch(option) {
default:
return -1;
}
}
/* }}} */

View File

@@ -202,8 +202,8 @@ MYSQL *repl_connect(MYSQL *mysql, const char *host, const char *user, const char
goto error; goto error;
/* try to connect to master */ /* try to connect to master */
if (!(mysql->methods->db_connect(mysql, data->host[MARIADB_MASTER], user, passwd, db, if (!(mariadb_api->mysql_real_connect(mysql, data->host[MARIADB_MASTER], user, passwd, db,
data->port[MARIADB_MASTER] ? data->port[MARIADB_MASTER] : port, unix_socket, clientflag))) data->port[MARIADB_MASTER] ? data->port[MARIADB_MASTER] : port, unix_socket, clientflag)))
goto error; goto error;
data->pvio[MARIADB_MASTER]= mysql->net.pvio; data->pvio[MARIADB_MASTER]= mysql->net.pvio;

View File

@@ -17,6 +17,7 @@ IF(REMOTEIO_PLUGIN_TYPE MATCHES "DYNAMIC")
# remote file plugin # remote file plugin
INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR})
SET(REMOTE_IO_SOURCES ${remote_io_RC} remote_io.c) SET(REMOTE_IO_SOURCES ${remote_io_RC} remote_io.c)
ADD_DEFINITIONS(-DHAVE_REMOTEIO_DYNAMIC=1)
ADD_LIBRARY(remote_io SHARED ${REMOTE_IO_SOURCES} ${CMAKE_SOURCE_DIR}/plugins/plugin.def) ADD_LIBRARY(remote_io SHARED ${REMOTE_IO_SOURCES} ${CMAKE_SOURCE_DIR}/plugins/plugin.def)
TARGET_LINK_LIBRARIES(remote_io ${CURL_LIBRARIES}) TARGET_LINK_LIBRARIES(remote_io ${CURL_LIBRARIES})
SET_TARGET_PROPERTIES(remote_io PROPERTIES PREFIX "") SET_TARGET_PROPERTIES(remote_io PROPERTIES PREFIX "")

View File

@@ -1,5 +1,5 @@
/************************************************************************************ /************************************************************************************
* Copyright (C) 2015 Monty Program AB * Copyright (C) 2015, 2016 Monty Program AB
* Copyright (c) 2003 Simtec Electronics * Copyright (c) 2003 Simtec Electronics
* *
* Re-implemented by Vincent Sanders <vince@kyllikki.org> with extensive * Re-implemented by Vincent Sanders <vince@kyllikki.org> with extensive
@@ -43,7 +43,6 @@
smb:// smb://
*/ */
#ifdef HAVE_CURL
#include <my_global.h> #include <my_global.h>
#include <my_sys.h> #include <my_sys.h>
#include <mysql.h> #include <mysql.h>
@@ -55,9 +54,12 @@
#include <string.h> #include <string.h>
#ifndef WIN32 #ifndef WIN32
#include <sys/time.h> #include <sys/time.h>
#else
#pragma comment(lib, "Ws2_32.lib")
#endif #endif
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <mariadb/ma_io.h>
/* Internal file structure */ /* Internal file structure */
@@ -89,11 +91,10 @@ typedef struct
CURLM *multi_handle= NULL; CURLM *multi_handle= NULL;
#ifndef HAVE_REMOTE_IO_DYNAMIC #ifndef HAVE_REMOTEIO_DYNAMIC
struct st_mysql_client_plugin remote_io_plugin= MARIADB_REMOTEIO_PLUGIN remote_io_plugin=
{
#else #else
struct st_mysql_client_plugin _mysql_client_plugin_declare_ = MARIADB_REMOTEIO_PLUGIN _mysql_client_plugin_declaration_ =
#endif #endif
{ {
MARIADB_CLIENT_REMOTEIO_PLUGIN, MARIADB_CLIENT_REMOTEIO_PLUGIN,
@@ -127,6 +128,7 @@ int ma_rio_deinit(void)
multi_handle= NULL; multi_handle= NULL;
} }
curl_global_cleanup(); curl_global_cleanup();
return 0;
} }
/* }}} */ /* }}} */
@@ -439,4 +441,3 @@ char *ma_rio_gets(char *ptr, size_t size, MA_FILE *file)
return ptr;/*success */ return ptr;/*success */
} }
#endif

View File

@@ -1,5 +1,5 @@
/************************************************************************************ /************************************************************************************
Copyright (C) 2015 MariaDB Corporation AB, Copyright (C) 2015,2016 MariaDB Corporation AB,
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public modify it under the terms of the GNU Library General Public
@@ -106,7 +106,7 @@ struct st_ma_pvio_methods pvio_socket_methods= {
#ifndef HAVE_SOCKET_DYNAMIC #ifndef HAVE_SOCKET_DYNAMIC
MARIADB_PVIO_PLUGIN pvio_socket_plugin= MARIADB_PVIO_PLUGIN pvio_socket_plugin=
#else #else
MARIADB_PVIO_PLUGIN _mysql_client_plugin_declare_ MARIADB_PVIO_PLUGIN _mysql_client_plugin_declaration_
#endif #endif
{ {
MARIADB_CLIENT_PVIO_PLUGIN, MARIADB_CLIENT_PVIO_PLUGIN,

View File

@@ -21,11 +21,11 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/unittest/mytap) ${CMAKE_SOURCE_DIR}/unittest/mytap)
ADD_DEFINITIONS(-DLIBMARIADB) ADD_DEFINITIONS(-DLIBMARIADB)
SET(API_TESTS "t_aurora" "async" "basic-t" "fetch" "charset" "logs" SET(API_TESTS "async" "basic-t" "fetch" "charset" "logs" "cursor" "errors" "view" "ps" "ps_bugs"
"cursor" "errors" "view" "ps" "ps_bugs" "sp" "result" "connection" "misc" "ps_new" "sqlite3" "thread" "dyncol" "features-10_2")
"sp" "result" "connection" "misc" "ps_new" "sqlite3" "thread"
"dyncol" "features-10_2")
#exclude following tests from ctests, since we need to run them maually with different credentials
SET(MANUAL_TESTS "t_aurora")
# Get finger print from server certificate # Get finger print from server certificate
IF(WITH_SSL) IF(WITH_SSL)
@@ -64,3 +64,8 @@ FOREACH(API_TEST ${API_TESTS})
ADD_TEST(${API_TEST} ${EXECUTABLE_OUTPUT_PATH}/${API_TEST}) ADD_TEST(${API_TEST} ${EXECUTABLE_OUTPUT_PATH}/${API_TEST})
SET_TESTS_PROPERTIES(${API_TEST} PROPERTIES TIMEOUT 120) SET_TESTS_PROPERTIES(${API_TEST} PROPERTIES TIMEOUT 120)
ENDFOREACH(API_TEST) ENDFOREACH(API_TEST)
FOREACH(API_TEST ${MANUAL_TESTS})
ADD_EXECUTABLE(${API_TEST} ${API_TEST}.c ${CMAKE_SOURCE_DIR}/libmariadb/getopt.c)
TARGET_LINK_LIBRARIES(${API_TEST} mytap libmariadb)
ENDFOREACH()

View File

@@ -35,11 +35,11 @@ static int test_conc75(MYSQL *my)
int rc; int rc;
MYSQL *mysql; MYSQL *mysql;
int i; int i;
my_bool reconnect= 1;
mysql= mysql_init(NULL); mysql= mysql_init(NULL);
mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
mysql->reconnect= 1;
mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS); mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS);
rc= mysql_query(mysql, "DROP TABLE IF EXISTS a"); rc= mysql_query(mysql, "DROP TABLE IF EXISTS a");
@@ -55,7 +55,7 @@ static int test_conc75(MYSQL *my)
{ {
ulong thread_id= mysql_thread_id(mysql); ulong thread_id= mysql_thread_id(mysql);
/* force reconnect */ /* force reconnect */
mysql->reconnect= 1; mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
diag("killing connection"); diag("killing connection");
mysql_kill(my, thread_id); mysql_kill(my, thread_id);
sleep(2); sleep(2);
@@ -700,6 +700,10 @@ static int test_reconnect_maxpackage(MYSQL *my)
MYSQL_RES *res; MYSQL_RES *res;
MYSQL_ROW row; MYSQL_ROW row;
char *query; char *query;
my_bool reconnect= 1;
SKIP_CONNECTION_HANDLER;
mysql= mysql_init(NULL);
SKIP_CONNECTION_HANDLER; SKIP_CONNECTION_HANDLER;
mysql= mysql_init(NULL); mysql= mysql_init(NULL);
@@ -707,7 +711,7 @@ static int test_reconnect_maxpackage(MYSQL *my)
FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema, FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
port, socketname, port, socketname,
CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql)); CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql));
mysql->reconnect= 1; mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
rc= mysql_query(mysql, "SELECT @@max_allowed_packet"); rc= mysql_query(mysql, "SELECT @@max_allowed_packet");
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);
@@ -753,12 +757,13 @@ static int test_compressed(MYSQL *my)
int rc; int rc;
MYSQL *mysql= mysql_init(NULL); MYSQL *mysql= mysql_init(NULL);
MYSQL_RES *res; MYSQL_RES *res;
my_bool reconnect= 1;
mysql_options(mysql, MYSQL_OPT_COMPRESS, (void *)1); mysql_options(mysql, MYSQL_OPT_COMPRESS, (void *)1);
FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema, FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema,
port, socketname, port, socketname,
CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql)); CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql));
mysql->reconnect= 1; mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
rc= mysql_query(mysql, "SHOW VARIABLES"); rc= mysql_query(mysql, "SHOW VARIABLES");
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);

View File

@@ -455,16 +455,21 @@ static int test_opt_reconnect(MYSQL *mysql)
{ {
my_bool my_true= TRUE; my_bool my_true= TRUE;
int rc; int rc;
my_bool reconnect;
printf("true: %d\n", TRUE);
mysql= mysql_init(NULL); mysql= mysql_init(NULL);
FAIL_IF(!mysql, "not enough memory"); FAIL_IF(!mysql, "not enough memory");
FAIL_UNLESS(mysql->reconnect == 0, "reconnect != 0"); mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect);
FAIL_UNLESS(reconnect == 0, "reconnect != 0");
rc= mysql_options(mysql, MYSQL_OPT_RECONNECT, &my_true); rc= mysql_options(mysql, MYSQL_OPT_RECONNECT, &my_true);
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);
FAIL_UNLESS(mysql->reconnect == 1, "reconnect != 1"); mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect);
FAIL_UNLESS(reconnect == 1, "reconnect != 1");
if (!(mysql_real_connect(mysql, hostname, username, if (!(mysql_real_connect(mysql, hostname, username,
password, schema, port, password, schema, port,
@@ -475,14 +480,16 @@ static int test_opt_reconnect(MYSQL *mysql)
return FAIL; return FAIL;
} }
FAIL_UNLESS(mysql->reconnect == 1, "reconnect != 1"); mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect);
FAIL_UNLESS(reconnect == 1, "reconnect != 1");
mysql_close(mysql); mysql_close(mysql);
mysql= mysql_init(NULL); mysql= mysql_init(NULL);
FAIL_IF(!mysql, "not enough memory"); FAIL_IF(!mysql, "not enough memory");
FAIL_UNLESS(mysql->reconnect == 0, "reconnect != 0"); mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect);
FAIL_UNLESS(reconnect == 0, "reconnect != 0");
if (!(mysql_real_connect(mysql, hostname, username, if (!(mysql_real_connect(mysql, hostname, username,
password, schema, port, password, schema, port,
@@ -493,7 +500,8 @@ static int test_opt_reconnect(MYSQL *mysql)
return FAIL; return FAIL;
} }
FAIL_UNLESS(mysql->reconnect == 0, "reconnect != 0"); mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect);
FAIL_UNLESS(reconnect == 0, "reconnect != 0");
mysql_close(mysql); mysql_close(mysql);
return OK; return OK;
@@ -538,16 +546,19 @@ static int test_reconnect(MYSQL *mysql)
my_bool my_true= TRUE; my_bool my_true= TRUE;
MYSQL *mysql1; MYSQL *mysql1;
int rc; int rc;
my_bool reconnect;
mysql1= mysql_init(NULL); mysql1= mysql_init(NULL);
FAIL_IF(!mysql1, "not enough memory"); FAIL_IF(!mysql1, "not enough memory");
FAIL_UNLESS(mysql1->reconnect == 0, "reconnect != 0"); mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect);
FAIL_UNLESS(reconnect == 0, "reconnect != 0");
rc= mysql_options(mysql1, MYSQL_OPT_RECONNECT, &my_true); rc= mysql_options(mysql1, MYSQL_OPT_RECONNECT, &my_true);
check_mysql_rc(rc, mysql1); check_mysql_rc(rc, mysql1);
FAIL_UNLESS(mysql1->reconnect == 1, "reconnect != 1"); mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect);
FAIL_UNLESS(reconnect == 1, "reconnect != 1");
if (!(mysql_real_connect(mysql1, hostname, username, if (!(mysql_real_connect(mysql1, hostname, username,
password, schema, port, password, schema, port,
@@ -558,7 +569,8 @@ static int test_reconnect(MYSQL *mysql)
return FAIL; return FAIL;
} }
FAIL_UNLESS(mysql1->reconnect == 1, "reconnect != 1"); mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect);
FAIL_UNLESS(reconnect == 1, "reconnect != 1");
diag("Thread_id before kill: %lu", mysql_thread_id(mysql1)); diag("Thread_id before kill: %lu", mysql_thread_id(mysql1));
mysql_kill(mysql, mysql_thread_id(mysql1)); mysql_kill(mysql, mysql_thread_id(mysql1));
@@ -570,7 +582,8 @@ static int test_reconnect(MYSQL *mysql)
check_mysql_rc(rc, mysql1); check_mysql_rc(rc, mysql1);
diag("Thread_id after kill: %lu", mysql_thread_id(mysql1)); diag("Thread_id after kill: %lu", mysql_thread_id(mysql1));
FAIL_UNLESS(mysql1->reconnect == 1, "reconnect != 1"); mysql_get_option(mysql1, MYSQL_OPT_RECONNECT, &reconnect);
FAIL_UNLESS(reconnect == 1, "reconnect != 1");
mysql_close(mysql1); mysql_close(mysql1);
return OK; return OK;
} }
@@ -647,8 +660,10 @@ int test_connection_timeout(MYSQL *my)
static int test_conc118(MYSQL *mysql) static int test_conc118(MYSQL *mysql)
{ {
int rc; int rc;
my_bool reconnect= 1;
mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
mysql->reconnect= 1;
mysql->options.unused_1= 1; mysql->options.unused_1= 1;
rc= mysql_kill(mysql, mysql_thread_id(mysql)); rc= mysql_kill(mysql, mysql_thread_id(mysql));
@@ -745,9 +760,10 @@ static int test_bind_address(MYSQL *my)
static int test_get_options(MYSQL *my) static int test_get_options(MYSQL *my)
{ {
MYSQL *mysql= mysql_init(NULL); MYSQL *mysql= mysql_init(NULL);
int options_int[]= {MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_LOCAL_INFILE, int options_int[]= {MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_LOCAL_INFILE,
MYSQL_OPT_RECONNECT, MYSQL_OPT_PROTOCOL, MYSQL_OPT_READ_TIMEOUT, MYSQL_OPT_WRITE_TIMEOUT, 0}; MYSQL_OPT_PROTOCOL, MYSQL_OPT_READ_TIMEOUT, MYSQL_OPT_WRITE_TIMEOUT, 0};
my_bool options_bool[]= {MYSQL_OPT_COMPRESS, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_SECURE_AUTH, my_bool options_bool[]= {MYSQL_OPT_RECONNECT, MYSQL_REPORT_DATA_TRUNCATION,
MYSQL_OPT_COMPRESS, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_SECURE_AUTH,
#ifdef _WIN32 #ifdef _WIN32
MYSQL_OPT_NAMED_PIPE, MYSQL_OPT_NAMED_PIPE,
#endif #endif
@@ -755,7 +771,7 @@ static int test_get_options(MYSQL *my)
int options_char[]= {MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP, MYSQL_SET_CHARSET_NAME, int options_char[]= {MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP, MYSQL_SET_CHARSET_NAME,
MYSQL_OPT_SSL_KEY, MYSQL_OPT_SSL_CA, MYSQL_OPT_SSL_CERT, MYSQL_OPT_SSL_CAPATH, MYSQL_OPT_SSL_KEY, MYSQL_OPT_SSL_CA, MYSQL_OPT_SSL_CERT, MYSQL_OPT_SSL_CAPATH,
MYSQL_OPT_SSL_CIPHER, MYSQL_OPT_BIND, MARIADB_OPT_SSL_FP, MARIADB_OPT_SSL_FP_LIST, MYSQL_OPT_SSL_CIPHER, MYSQL_OPT_BIND, MARIADB_OPT_SSL_FP, MARIADB_OPT_SSL_FP_LIST,
MARIADB_OPT_SSL_PASSWORD, 0}; MARIADB_OPT_SSL_PASSPHRASE, 0};
char *init_command[3]= {"SET @a:=1", "SET @b:=2", "SET @c:=3"}; char *init_command[3]= {"SET @a:=1", "SET @b:=2", "SET @c:=3"};
int elements= 0; int elements= 0;

View File

@@ -957,6 +957,7 @@ static int test_conc_114(MYSQL *mysql)
/* run with valgrind */ /* run with valgrind */
static int test_conc117(MYSQL *mysql) static int test_conc117(MYSQL *mysql)
{ {
my_bool reconnect= 1;
MYSQL *my= mysql_init(NULL); MYSQL *my= mysql_init(NULL);
FAIL_IF(!mysql_real_connect(my, hostname, username, password, schema, FAIL_IF(!mysql_real_connect(my, hostname, username, password, schema,
port, socketname, 0), mysql_error(my)); port, socketname, 0), mysql_error(my));
@@ -964,7 +965,7 @@ static int test_conc117(MYSQL *mysql)
mysql_kill(my, mysql_thread_id(my)); mysql_kill(my, mysql_thread_id(my));
sleep(5); sleep(5);
my->reconnect= 1; mysql_options(my, MYSQL_OPT_RECONNECT, &reconnect);
mysql_query(my, "SET @a:=1"); mysql_query(my, "SET @a:=1");
mysql_close(my); mysql_close(my);
@@ -982,6 +983,7 @@ static int test_remote1(MYSQL *mysql)
if (!remote_plugin) if (!remote_plugin)
{ {
diag("skip - no remote io plugin available"); diag("skip - no remote io plugin available");
diag("error: %s", mysql_error(mysql));
return SKIP; return SKIP;
} }
@@ -1043,7 +1045,7 @@ static int test_get_info(MYSQL *mysql)
rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_VERSION_ID, &sval); rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_SERVER_VERSION_ID, &sval);
FAIL_IF(rc, "mysql_get_info failed"); FAIL_IF(rc, "mysql_get_info failed");
diag("server_version_id: %d", sval); diag("server_version_id: %d", sval);
rc= mariadb_get_infov(mysql, MARIADB_CHARSET_INFO, &cs); rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_CHARSET_INFO, &cs);
FAIL_IF(rc, "mysql_get_info failed"); FAIL_IF(rc, "mysql_get_info failed");
diag("charset name: %s", cs.csname); diag("charset name: %s", cs.csname);
rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_PVIO_TYPE, &ival); rc= mariadb_get_infov(mysql, MARIADB_CONNECTION_PVIO_TYPE, &ival);

View File

@@ -29,6 +29,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <memory.h> #include <memory.h>
#include <errmsg.h> #include <errmsg.h>
#ifndef WIN32
#include <pthread.h>
#endif
#ifndef OK #ifndef OK
# define OK 0 # define OK 0
#endif #endif
@@ -374,7 +378,6 @@ int check_variable(MYSQL *mysql, char *variable, char *value)
*/ */
MYSQL *test_connect(struct my_tests_st *test) { MYSQL *test_connect(struct my_tests_st *test) {
MYSQL *mysql; MYSQL *mysql;
char query[255];
int i= 0; int i= 0;
int timeout= 10; int timeout= 10;
int truncation_report= 1; int truncation_report= 1;
@@ -401,32 +404,13 @@ MYSQL *test_connect(struct my_tests_st *test) {
} }
} }
if (!(mysql_real_connect(mysql, hostname, username, password, if (!(mysql_real_connect(mysql, hostname, username, password,
NULL, port, socketname, (test) ? test->connect_flags:0))) schema, port, socketname, (test) ? test->connect_flags:0)))
{ {
diag("Couldn't establish connection to server %s. Error (%d): %s", diag("Couldn't establish connection to server %s. Error (%d): %s",
hostname, mysql_errno(mysql), mysql_error(mysql)); hostname, mysql_errno(mysql), mysql_error(mysql));
mysql_close(mysql); mysql_close(mysql);
return(NULL); return(NULL);
} }
/* change database or create if it doesn't exist */
if (mysql_select_db(mysql, schema)) {
diag("Error number: %d", mysql_errno(mysql));
if(mysql_errno(mysql) == 1049) {
sprintf(query, "CREATE DATABASE %s", schema);
if (mysql_query(mysql, query)) {
diag("Can't create database %s", schema);
mysql_close(mysql);
return NULL;
}
} else {
diag("Error (%d): %s", mysql_errno(mysql), mysql_error(mysql));
mysql_close(mysql);
return NULL;
}
}
return(mysql); return(mysql);
} }
@@ -526,6 +510,7 @@ void run_tests(struct my_tests_st *test) {
} }
} }
if (mysql_default) { if (mysql_default) {
diag("close default");
mysql_close(mysql_default); mysql_close(mysql_default);
} }
mysql_server_end(); mysql_server_end();

View File

@@ -52,12 +52,13 @@ static int test_conc83(MYSQL *my)
MYSQL_STMT *stmt; MYSQL_STMT *stmt;
int rc; int rc;
MYSQL *mysql= mysql_init(NULL); MYSQL *mysql= mysql_init(NULL);
my_bool reconnect= 1;
char *query= "SELECT 1,2,3 FROM DUAL"; char *query= "SELECT 1,2,3 FROM DUAL";
stmt= mysql_stmt_init(mysql); stmt= mysql_stmt_init(mysql);
mysql->reconnect= 1; mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
FAIL_IF(!(mysql_real_connect(mysql, hostname, username, password, FAIL_IF(!(mysql_real_connect(mysql, hostname, username, password,
schema, port, socketname, 0)), "mysql_real_connect failed"); schema, port, socketname, 0)), "mysql_real_connect failed");
@@ -69,7 +70,7 @@ static int test_conc83(MYSQL *my)
rc= mysql_ping(mysql); rc= mysql_ping(mysql);
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);
rc= mysql_stmt_prepare(stmt, query, strlen(query)); rc= mysql_stmt_prepare(stmt, query, -1);
check_stmt_rc(rc, stmt); check_stmt_rc(rc, stmt);
diag("Ok"); diag("Ok");
@@ -77,7 +78,7 @@ static int test_conc83(MYSQL *my)
rc= mysql_kill(mysql, mysql_thread_id(mysql)); rc= mysql_kill(mysql, mysql_thread_id(mysql));
sleep(2); sleep(2);
rc= mysql_stmt_prepare(stmt, query, strlen(query)); rc= mysql_stmt_prepare(stmt, query, -1);
FAIL_IF(!rc, "Error expected"); FAIL_IF(!rc, "Error expected");
mysql_stmt_close(stmt); mysql_stmt_close(stmt);
@@ -97,7 +98,7 @@ static int test_conc60(MYSQL *mysql)
rc= mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void *)&x); rc= mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void *)&x);
rc= mysql_stmt_prepare(stmt, query, strlen(query)); rc= mysql_stmt_prepare(stmt, query, -1);
if (rc && mysql_stmt_errno(stmt) == 1146) { if (rc && mysql_stmt_errno(stmt) == 1146) {
diag("Internal test - customer data not available"); diag("Internal test - customer data not available");
mysql_stmt_close(stmt); mysql_stmt_close(stmt);
@@ -4544,9 +4545,9 @@ static int test_stmt_close(MYSQL *mysql)
unsigned int count; unsigned int count;
int rc; int rc;
char query[MAX_TEST_QUERY_LENGTH]; char query[MAX_TEST_QUERY_LENGTH];
my_bool reconnect= 1;
mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
mysql->reconnect= 1;
/* set AUTOCOMMIT to ON*/ /* set AUTOCOMMIT to ON*/
mysql_autocommit(mysql, TRUE); mysql_autocommit(mysql, TRUE);
@@ -4644,9 +4645,8 @@ static int test_new_date(MYSQL *mysql)
MYSQL_BIND bind[1]; MYSQL_BIND bind[1];
int rc; int rc;
char buffer[50]; char buffer[50];
my_bool reconnect= 1;
mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
mysql->reconnect= 1;
/* set AUTOCOMMIT to ON*/ /* set AUTOCOMMIT to ON*/
mysql_autocommit(mysql, TRUE); mysql_autocommit(mysql, TRUE);

View File

@@ -3909,7 +3909,111 @@ static int test_conc141(MYSQL *mysql)
return OK; return OK;
} }
static int test_conc154(MYSQL *mysql)
{
MYSQL_STMT *stmt;
const char *stmtstr= "SELECT * FROM t1";
int rc;
/* 1st: empty result set without free_result */
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
check_mysql_rc(rc, mysql);
rc= mysql_query(mysql, "CREATE TABLE t1 (a varchar(20))");
check_mysql_rc(rc, mysql);
stmt= mysql_stmt_init(mysql);
rc= mysql_stmt_prepare(stmt, stmtstr, strlen(stmtstr));
check_stmt_rc(rc, stmt);
rc= mysql_stmt_execute(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_store_result(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_execute(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_store_result(stmt);
check_stmt_rc(rc, stmt);
mysql_stmt_close(stmt);
/* 2nd: empty result set with free_result */
stmt= mysql_stmt_init(mysql);
rc= mysql_stmt_prepare(stmt, stmtstr, strlen(stmtstr));
check_stmt_rc(rc, stmt);
rc= mysql_stmt_execute(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_store_result(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_free_result(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_execute(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_store_result(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_free_result(stmt);
check_stmt_rc(rc, stmt);
mysql_stmt_close(stmt);
/* 3rd: non empty result without free_result */
rc= mysql_query(mysql, "INSERT INTO t1 VALUES ('test_conc154')");
check_mysql_rc(rc, mysql);
stmt= mysql_stmt_init(mysql);
rc= mysql_stmt_prepare(stmt, stmtstr, strlen(stmtstr));
check_stmt_rc(rc, stmt);
rc= mysql_stmt_execute(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_store_result(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_execute(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_store_result(stmt);
check_stmt_rc(rc, stmt);
mysql_stmt_close(stmt);
/* 4th non empty result set with free_result */
stmt= mysql_stmt_init(mysql);
rc= mysql_stmt_prepare(stmt, stmtstr, strlen(stmtstr));
check_stmt_rc(rc, stmt);
rc= mysql_stmt_execute(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_store_result(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_free_result(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_execute(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_store_result(stmt);
check_stmt_rc(rc, stmt);
rc= mysql_stmt_free_result(stmt);
check_stmt_rc(rc, stmt);
mysql_stmt_close(stmt);
return OK;
}
struct my_tests_st my_tests[] = { struct my_tests_st my_tests[] = {
{"test_conc154", test_conc154, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
{"test_conc141", test_conc141, TEST_CONNECTION_NEW, 0, NULL , NULL}, {"test_conc141", test_conc141, TEST_CONNECTION_NEW, 0, NULL , NULL},
{"test_conc67", test_conc67, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, {"test_conc67", test_conc67, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
{"test_conc_5", test_conc_5, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, {"test_conc_5", test_conc_5, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},

View File

@@ -932,6 +932,7 @@ select 1;\
DROP TABLE IF EXISTS test_multi_tab"; DROP TABLE IF EXISTS test_multi_tab";
uint count, exp_value; uint count, exp_value;
uint rows[]= {0, 0, 2, 1, 3, 2, 2, 1, 1, 0, 0, 1, 0}; uint rows[]= {0, 0, 2, 1, 3, 2, 2, 1, 1, 0, 0, 1, 0};
my_bool reconnect= 1;
/* /*
First test that we get an error for multi statements First test that we get an error for multi statements
@@ -950,7 +951,7 @@ DROP TABLE IF EXISTS test_multi_tab";
mysql_close(mysql); mysql_close(mysql);
mysql= mysql_local; mysql= mysql_local;
mysql_local->reconnect= 1; mysql_options(mysql_local, MYSQL_OPT_RECONNECT, &reconnect);
rc= mysql_query(mysql_local, query); rc= mysql_query(mysql_local, query);
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);

View File

@@ -53,18 +53,7 @@ static int check_cipher(MYSQL *mysql)
return 1; return 1;
diag("cipher: %s", cipher); diag("cipher: %s", cipher);
#ifdef HAVE_GNUTLS return 0;
{
return strcmp(cipher, "AES-128-GCM");
}
#elif HAVE_OPENSSL
if (!strcmp(cipher, "DHE-RSA-AES256-SHA") ||
!strcmp(cipher, "DHE-RSA-AES256-GCM-SHA384"))
return 0;
#elif HAVE_SCHANNEL
return strcmp(cipher, "CALG_AES_256");
#endif
return 1;
} }
static int create_ssl_user(const char *ssluser, my_bool is_X509) static int create_ssl_user(const char *ssluser, my_bool is_X509)
@@ -90,6 +79,8 @@ static int create_ssl_user(const char *ssluser, my_bool is_X509)
rc= mysql_query(mysql, "FLUSH PRIVILEGES"); rc= mysql_query(mysql, "FLUSH PRIVILEGES");
check_mysql_rc(rc,mysql); check_mysql_rc(rc,mysql);
mysql_close(mysql);
return rc; return rc;
} }
@@ -388,7 +379,7 @@ static int test_password_protected(MYSQL *my)
"@CMAKE_SOURCE_DIR@/unittest/libmariadb/certs/client-cert.pem", "@CMAKE_SOURCE_DIR@/unittest/libmariadb/certs/client-cert.pem",
"@CMAKE_SOURCE_DIR@/unittest/libmariadb/certs/ca-cert.pem", 0, 0); "@CMAKE_SOURCE_DIR@/unittest/libmariadb/certs/ca-cert.pem", 0, 0);
mysql_options(mysql, MARIADB_OPT_SSL_PASSWORD, "qwerty"); mysql_options(mysql, MARIADB_OPT_SSL_PASSPHRASE, "qwerty");
FAIL_IF(!mysql_real_connect(mysql, hostname, ssluser, sslpw, schema, FAIL_IF(!mysql_real_connect(mysql, hostname, ssluser, sslpw, schema,
port, socketname, 0), mysql_error(mysql)); port, socketname, 0), mysql_error(mysql));
@@ -775,7 +766,7 @@ static int test_ssl_fp_list(MYSQL *unused)
static int test_ssl_version(MYSQL *mysql) static int test_ssl_version(MYSQL *mysql)
{ {
unsigned int iversion; unsigned int iversion;
char *version; const char *version, *library;
MYSQL *my; MYSQL *my;
if (check_skip_ssl()) if (check_skip_ssl())
@@ -794,6 +785,9 @@ static int test_ssl_version(MYSQL *mysql)
mariadb_get_infov(my, MARIADB_CONNECTION_SSL_VERSION, &version); mariadb_get_infov(my, MARIADB_CONNECTION_SSL_VERSION, &version);
diag("protocol: %s", version); diag("protocol: %s", version);
mariadb_get_infov(my, MARIADB_SSL_LIBRARY, &library);
diag("library: %s", library);
mysql_close(my); mysql_close(my);
return OK; return OK;

View File

@@ -2,13 +2,22 @@
*/ */
#include "my_test.h" #include "my_test.h"
#include "ma_pvio.h"
static int aurora1(MYSQL *mysql) static int aurora1(MYSQL *my)
{ {
int rc; int rc;
my_bool read_only= 1; my_bool read_only= 1;
char *primary, *replica; const char *primary, *my_schema;
MYSQL_RES *res; MYSQL_RES *res;
MYSQL *mysql= mysql_init(NULL);
if (!mysql_real_connect(mysql, hostname, username, password, schema, port, NULL, 0))
{
diag("Error: %s", mysql_error(mysql));
mysql_close(mysql);
return FAIL;
}
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);
@@ -19,7 +28,7 @@ static int aurora1(MYSQL *mysql)
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1, 'foo'), (2, 'bar')"); rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1, 'foo'), (2, 'bar')");
check_mysql_rc(rc, mysql); check_mysql_rc(rc, mysql);
primary= mysql->host; mariadb_get_infov(mysql, MARIADB_CONNECTION_HOST, &primary);
diag("primary: %s", primary); diag("primary: %s", primary);
mysql_options(mysql, MARIADB_OPT_CONNECTION_READ_ONLY, &read_only); mysql_options(mysql, MARIADB_OPT_CONNECTION_READ_ONLY, &read_only);
@@ -37,22 +46,108 @@ static int aurora1(MYSQL *mysql)
diag("Num_rows: %d", mysql_num_rows(res)); diag("Num_rows: %d", mysql_num_rows(res));
mysql_free_result(res); mysql_free_result(res);
replica= mysql->host; mariadb_get_infov(mysql, MARIADB_CONNECTION_SCHEMA, &my_schema);
diag("replica: %s", replica); diag("db: %s", my_schema);
diag("db: %s", mysql->db);
mysql_close(mysql);
return OK; return OK;
} }
static int test_wrong_user(MYSQL *my)
{
MYSQL *mysql= mysql_init(NULL);
if (mysql_real_connect(mysql, hostname, "wrong_user", NULL, NULL, 0, NULL, 0))
{
diag("Error expected");
mysql_close(mysql);
return FAIL;
}
mysql_close(mysql);
return OK;
}
static int test_reconnect(MYSQL *my)
{
MYSQL *mysql= mysql_init(NULL);
MYSQL_RES *res;
my_bool read_only= 1;
int rc;
my_bool reconnect= 1;
const char *aurora_host;
mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
if (!mysql_real_connect(mysql, hostname, username, password, schema, port, NULL, 0))
{
diag("Error: %s", mysql_error(mysql));
mysql_close(mysql);
return FAIL;
}
mariadb_get_infov(mysql, MARIADB_CONNECTION_HOST, &aurora_host);
diag("host: %s", aurora_host);
rc= mysql_query(mysql, "DROP TABLE IF EXISTS tx01");
check_mysql_rc(rc, mysql);
rc= mysql_query(mysql, "CREATE TABLE tx01 (a int)");
check_mysql_rc(rc, mysql);
/* we force cluster restart and promoting new primary:
* we wait for 50 seconds - however there is no guarantee that
* cluster was restarted already - so this test might fail */
system("/usr/local/aws/bin/aws rds failover-db-cluster --db-cluster-identifier instance-1-cluster");
sleep(50);
diag("Q1");
rc= mysql_query(mysql, "INSERT INTO tx01 VALUES (1)");
if (!rc)
diag("error expected!");
diag("Error: %s", mysql_error(mysql));
diag("Q2");
rc= mysql_query(mysql, "INSERT INTO tx01 VALUES (1)");
if (rc)
{
diag("no error expected!");
diag("Error: %s", mysql_error(mysql));
diag("host: %s", mysql->host);
}
else
{
mariadb_get_infov(mysql, MARIADB_CONNECTION_HOST, &aurora_host);
diag("host: %s", aurora_host);
}
mysql_options(mysql, MARIADB_OPT_CONNECTION_READ_ONLY, &read_only);
rc= mysql_query(mysql, "SELECT * from tx01");
check_mysql_rc(rc, mysql);
if ((res= mysql_store_result(mysql)))
{
diag("num_rows: %d", mysql_num_rows(res));
mysql_free_result(res);
}
mariadb_get_infov(mysql, MARIADB_CONNECTION_HOST, &aurora_host);
diag("host: %s", aurora_host);
mysql_close(mysql);
return OK;
}
struct my_tests_st my_tests[] = { struct my_tests_st my_tests[] = {
{"aurora1", aurora1, TEST_CONNECTION_NEW, 0, NULL, NULL}, {"aurora1", aurora1, TEST_CONNECTION_NONE, 0, NULL, NULL},
{"test_wrong_user", test_wrong_user, TEST_CONNECTION_NONE, 0, NULL, NULL},
{"test_reconnect", test_reconnect, TEST_CONNECTION_NONE, 0, NULL, NULL},
{NULL, NULL, 0, 0, NULL, NULL} {NULL, NULL, 0, 0, NULL, NULL}
}; };
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
mysql_library_init(0,0,NULL); mysql_library_init(0,0,NULL);
if (argc > 1) if (argc > 1)

View File

@@ -51,6 +51,7 @@
</RegistryKey> </RegistryKey>
</Component> </Component>
<Component Id="Library" Guid="89E28283-23AE-4F10-B743-B5FA485E9F9A" KeyPath="yes" DiskId="1" Directory="instlib" Win64="@IS_WIN64@"> <Component Id="Library" Guid="89E28283-23AE-4F10-B743-B5FA485E9F9A" KeyPath="yes" DiskId="1" Directory="instlib" Win64="@IS_WIN64@">
<Environment Id="LIB_PATH" Name="PATH" Value="[instlib]" Permanent="no" Action="set" Part="last" System="yes"/>
<File Id="libdll" Name="libmariadb.dll" DiskId="1" Source="@CLIENT_LIB_DIR@/libmariadb.dll" /> <File Id="libdll" Name="libmariadb.dll" DiskId="1" Source="@CLIENT_LIB_DIR@/libmariadb.dll" />
<File Id="libdllimp" Name="libmariadb.lib" DiskId="1" Source="@CLIENT_LIB_DIR@/libmariadb.lib" /> <File Id="libdllimp" Name="libmariadb.lib" DiskId="1" Source="@CLIENT_LIB_DIR@/libmariadb.lib" />
<File Id="libstatic" Name="mariadbclient.lib" DiskId="1" Source="@CLIENT_LIB_DIR@/mariadbclient.lib" /> <File Id="libstatic" Name="mariadbclient.lib" DiskId="1" Source="@CLIENT_LIB_DIR@/mariadbclient.lib" />
@@ -61,6 +62,7 @@
Source="@CLIENT_BIN_DIR@/mariadb_client_plugin_info.exe" /> Source="@CLIENT_BIN_DIR@/mariadb_client_plugin_info.exe" />
</Component> </Component>
<Component Id="Plugins" Guid="5B2E98C9-DFF2-4129-8360-C6AD16F6BBEA" KeyPath="yes" DiskId="1" Directory="instlib_plugin" Win64="@IS_WIN64@"> <Component Id="Plugins" Guid="5B2E98C9-DFF2-4129-8360-C6AD16F6BBEA" KeyPath="yes" DiskId="1" Directory="instlib_plugin" Win64="@IS_WIN64@">
<Environment Id="PLUGIN_PATH" Name="PATH" Value="[instlib_plugin]" Permanent="no" Action="set" Part="last" System="yes"/>
@MARIADB_PLUGINS@ @MARIADB_PLUGINS@
</Component> </Component>
<Component Id="Includes" Guid="5CFB93CC-FC30-4E13-B665-E52690AB56E3" KeyPath="yes" Directory="instinclude" DiskId="1" Win64="@IS_WIN64@"> <Component Id="Includes" Guid="5CFB93CC-FC30-4E13-B665-E52690AB56E3" KeyPath="yes" Directory="instinclude" DiskId="1" Win64="@IS_WIN64@">