mysql-audit/include/mysql_inc.h

285 lines
9.6 KiB
C++

#ifndef MYSQL_INCL_H
#define MYSQL_INCL_H
#ifndef HAVE_CONFIG_H
#define HAVE_CONFIG_H
#endif
#define MYSQL_DYNAMIC_PLUGIN 1
#define MYSQL_SERVER 1
// Fix for VIO. We don't want to using method mapping as then a change in
// the struct will cause the offsets compiled with to be wrong.
// As is the case with ndb which uses a version of Vio with support for
// ipv6 similar to 5.5 but different from 5.1
#define DONT_MAP_VIO
#include <my_config.h>
#include <mysql_version.h>
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100307
#include <my_global.h>
#endif
#if MYSQL_VERSION_ID >= 80032 && !defined(MARIADB_BASE_VERSION)
#define TABLE_LIST Table_ref
#endif
// These two are not present in 5.7.9
#if MYSQL_VERSION_ID < 50709
#include <my_pthread.h>
#include <sql_priv.h>
#endif
#include <mysql/plugin.h>
#if defined(MARIADB_BASE_VERSION)
#include <mysql/psi/psi_memory.h>
#include <mysql/psi/psi.h>
#endif
#if MYSQL_VERSION_ID >= 50600
// From 5.6 we use the audit plugin interface
#include <mysql/plugin_audit.h>
#endif
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100307
// From MariaDB 10.3 we include macro definitions for items like MY_GNUC_PREREQ
#include <my_compiler.h>
#endif
#include <sql_parse.h>
#include <sql_class.h>
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 80019
#include <mysql/components/services/mysql_connection_attributes_iterator.h>
#include <mysql/components/my_service.h>
#include <mysql/service_plugin_registry.h>
#endif
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 80000
using my_bool = bool;
#if MYSQL_VERSION_ID < 80012
#define PLUGIN_VAR_NOSYSVAR 0x0400
#endif
#include <sql/item.h>
#include <sql/log.h>
#include <sql/log_event.h>
#include <sql/mysqld.h>
#include <sql/protocol.h>
#include <sql/sql_lex.h>
#else
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID < 100504
#include <my_global.h>
#endif
typedef struct st_mysql_sys_var SYS_VAR;
#endif
#include <sql_connect.h>
#include <sql/sql_base.h>
#include <sql/sql_table.h>
#include <sql/sql_view.h>
#include <sql/sql_error.h>
// TODO: use mysql mutex instead of pthread
/*
#define pthread_mutex_lock mysql_mutex_lock
#define pthread_mutex_unlock mysql_mutex_unlock
#define pthread_mutex_init mysql_mutex_init
#define pthread_mutex_destroy mysql_mutex_destroy
#define pthread_mutex_t mysql_mutex_t
*/
#if MYSQL_VERSION_ID >= 50709
#include <sql/log.h>
#if ! defined(MARIADB_BASE_VERSION)
#include <sql/sql_plugin.h>
#include <sql/auth/auth_common.h>
#endif
#endif
#include <violite.h>
#include <events.h>
#include <my_md5.h>
#include <my_dir.h>
#include <my_sys.h>
// 5.5 use my_free with a single param. 5.1 use with 2 params
// based on: http://bazaar.launchpad.net/~mysql/myodbc/5.1/view/head:/util/stringutil.h
#ifndef x_free
# if MYSQL_VERSION_ID >= 50500
# define x_free(A) { void *tmp= (A); if (tmp) my_free((char *) tmp); }
# else
# define x_free(A) { void *tmp= (A); if (tmp) my_free((char *) tmp,MYF(0)); }
# endif
#endif
#if defined(MARIADB_BASE_VERSION)
// MariaDB has a kill service that overrides thd_killed as a macro. It also has thd_killed function defined for backwards compatibility, so we redefine it.
#undef thd_killed
extern "C" int thd_killed(const MYSQL_THD thd);
// MariadDB 10.0.10 removed the include for thd_security_context
#if MYSQL_VERSION_ID >= 100010
extern "C" char *thd_security_context(MYSQL_THD thd, char *buffer, unsigned int length, unsigned int max_query_len);
#endif
#endif
//Define HAVE_SESS_CONNECT_ATTRS. We define it for mysql 5.6 and above and MariaDB 10.0 and above
#if MYSQL_VERSION_ID >= 50600
#define HAVE_SESS_CONNECT_ATTRS 1
#endif
#include <storage/perfschema/pfs_instr.h>
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 80000
#include <dlfcn.h>
#endif
namespace compat {
/*************************/
/* my_getsystime */
/*************************/
#if defined(MARIADB_BASE_VERSION)
// MariaDB doesn't have my_getsystime (returns 100 nano seconds) function. They replaced with my_hrtime_t my_hrtime() which returns microseconds
static inline unsigned long long int my_getsystime() { return (my_hrtime()).val * 10; }
#elif MYSQL_VERSION_ID < 80000
static inline unsigned long long int my_getsystime() { return ::my_getsystime(); }
#else
static inline unsigned long long int my_getsystime() {
#ifdef HAVE_CLOCK_GETTIME
// Performance regression testing showed this to be preferable
struct timespec tp;
clock_gettime(CLOCK_REALTIME, &tp);
return (static_cast<unsigned long long int>(tp.tv_sec) * 10000000 +
static_cast<unsigned long long int>(tp.tv_nsec) / 100);
#else
return std::chrono::duration_cast<
std::chrono::duration<std::int64_t, std::ratio<1, 10000000>>>(
UTC_clock::now().time_since_epoch())
.count();
#endif /* HAVE_CLOCK_GETTIME */
}
#endif
/*********************************************/
/* vio_socket_connect */
/*********************************************/
#if MYSQL_VERSION_ID >= 50600
#ifndef MYSQL_VIO
#define MYSQL_VIO Vio*
#endif
#if defined(MARIADB_BASE_VERSION) || MYSQL_VERSION_ID < 80000
static inline bool vio_socket_connect(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, int timeout)
{
return ::vio_socket_connect(vio, addr, len, timeout);
}
#else
/*********************************************/
/* */
/* resolve the symbols manually to permit */
/* loading of the plugin in their absence */
/* */
/*********************************************/
extern bool (*_vio_socket_connect)(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, int timeout);
extern bool (*_vio_socket_connect_80016)(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, bool nonblocking, int timeout);
extern bool (*_vio_socket_connect_80020)(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, bool nonblocking, int timeout, bool *connect_done);
static inline bool vio_socket_connect(MYSQL_VIO vio, struct sockaddr *addr, socklen_t len, int timeout)
{
if (_vio_socket_connect) return _vio_socket_connect(vio, addr, len, timeout);
if (_vio_socket_connect_80016) return _vio_socket_connect_80016(vio, addr, len, false, timeout);
if (_vio_socket_connect_80020) return _vio_socket_connect_80020(vio, addr, len, false, timeout, nullptr);
return true;
}
static inline bool init_vio_socket_connect()
{
void* handle = dlopen(NULL, RTLD_LAZY);
if (!handle)
return false;
_vio_socket_connect = (decltype(_vio_socket_connect))dlsym(handle, "_Z18vio_socket_connectP3VioP8sockaddrji");
_vio_socket_connect_80016 = (decltype(_vio_socket_connect_80016))dlsym(handle, "_Z18vio_socket_connectP3VioP8sockaddrjbi");
_vio_socket_connect_80020 = (decltype(_vio_socket_connect_80020))dlsym(handle, "_Z18vio_socket_connectP3VioP8sockaddrjbiPb");
dlclose(handle);
return _vio_socket_connect || _vio_socket_connect_80016 || _vio_socket_connect_80020;
}
extern const std::string & (*_str_session_80026)(int cmd);
extern const LEX_STRING *_command_name;
static inline const char* str_session(int cmd)
{
if (_str_session_80026) return _str_session_80026(cmd).c_str();
if (_command_name) return _command_name[cmd].str;
return "";
}
static inline bool init_str_session()
{
void* handle = dlopen(NULL, RTLD_LAZY);
if (!handle)
return false;
_command_name = (decltype(_command_name))dlsym(handle, "command_name");
_str_session_80026 = ((decltype(_str_session_80026))dlsym(handle, "_ZN13Command_names11str_sessionE19enum_server_command") != NULL)
? (decltype(_str_session_80026))dlsym(handle, "_ZN13Command_names11str_sessionE19enum_server_command") :
(decltype(_str_session_80026))dlsym(handle, "_ZN13Command_names11str_sessionB5cxx11E19enum_server_command");
dlclose(handle);
return _command_name || _str_session_80026;
}
#endif
#endif
/*********************************************/
/* PFS_thread::get_current_thread */
/*********************************************/
#if defined(HAVE_SESS_CONNECT_ATTRS) && defined(MARIADB_BASE_VERSION)
typedef const ::PFS_thread* (*pfs_thread_t)();
extern pfs_thread_t _pfs_thread_get_current_thread;
extern PSI_v1* _psi_interface;
namespace PFS_thread {
static inline const ::PFS_thread* get_current_thread()
{
// Try PFS_thread and PSI_hook when MariaDB
if (_pfs_thread_get_current_thread) return _pfs_thread_get_current_thread();
if (_psi_interface) return (::PFS_thread*)_psi_interface->get_thread();
return NULL;
}
}
static inline bool init_PFS_thread_get_current_thread()
{
// obtain the PFS_thread::get_current_thread() address if it is exported
void* handle = dlopen(NULL, RTLD_LAZY);
if (handle) {
_pfs_thread_get_current_thread = (pfs_thread_t)dlsym(handle, "_ZN10PFS_thread18get_current_threadEv");
dlclose(handle);
}
// obtain the PSI interface address
if (PSI_hook)
_psi_interface = (PSI_v1*)PSI_hook->get_interface(PSI_VERSION_1);
if (!_pfs_thread_get_current_thread && !_psi_interface)
sql_print_information("Failed to initialize Performance Schema. 'osuser' and 'appname' will not be avalilable.");
return true;
}
#elif defined(HAVE_SESS_CONNECT_ATTRS)
namespace PFS_thread {
static inline const ::PFS_thread* get_current_thread()
{
// Use PFS_thread when MySQL
return ::PFS_thread::get_current_thread();
}
}
#endif
static inline bool init()
{
#if !defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 80000
return init_vio_socket_connect() && init_str_session();
#elif defined(HAVE_SESS_CONNECT_ATTRS) && defined(MARIADB_BASE_VERSION)
return init_PFS_thread_get_current_thread();
#else
return true;
#endif
}
}
#endif // MYSQL_INCL_H