MySQL handshake has a configurable version_string

MySQL handshake has no a configurable version_string parameter in
service section.
The default value is the server version of the embedded mysqld library.

Set option example:

version_string=5.5.37-MariaDB-log

Default is similar to:

5.5.35-MariaDB
This commit is contained in:
MassimilianoPinto 2014-05-07 18:08:28 +02:00
parent bdefa5c3c8
commit 29932f7fc8
6 changed files with 73 additions and 133 deletions

View File

@ -29,6 +29,7 @@
* 06/02/14 Massimiliano Pinto Added support for enable/disable root user in services
* 14/02/14 Massimiliano Pinto Added enable_root_user in the service_params list
* 11/03/14 Massimiliano Pinto Added Unix socket support
* 11/05/14 Massimiliano Pinto Added version_string support to service
*
* @endverbatim
*/
@ -43,6 +44,7 @@
#include <monitor.h>
#include <skygw_utils.h>
#include <log_manager.h>
#include <mysql.h>
extern int lm_enabled_logfiles_bitmask;
@ -56,6 +58,7 @@ static void check_config_objects(CONFIG_CONTEXT *context);
static char *config_file = NULL;
static GATEWAY_CONF gateway;
char *version_string = NULL;
/**
* Config item handler for the ini file reader
@ -116,6 +119,21 @@ config_load(char *file)
CONFIG_CONTEXT config;
int rval;
MYSQL *conn;
conn = mysql_init(NULL);
if (conn) {
if (mysql_real_connect(conn, NULL, NULL, NULL, NULL, 0, NULL, 0)) {
char *ptr;
version_string = (char *)mysql_get_server_info(conn);
ptr = strstr(version_string, "-embedded");
if (ptr) {
*ptr = '\0';
}
}
mysql_close(conn);
}
global_defaults();
config.object = "";
@ -146,6 +164,11 @@ int rval;
if (!config_file)
return 0;
if (gateway.version_string)
free(gateway.version_string);
global_defaults();
config.object = "";
@ -202,6 +225,15 @@ int error_count = 0;
config_get_value(obj->parameters, "passwd");
char *enable_root_user =
config_get_value(obj->parameters, "enable_root_user");
char *version_string = config_get_value(obj->parameters, "version_string");
if (version_string) {
((SERVICE *)(obj->element))->version_string = strdup(version_string);
} else {
if (gateway.version_string)
((SERVICE *)(obj->element))->version_string = strdup(gateway.version_string);
}
if (enable_root_user)
serviceEnableRootUser(obj->element, atoi(enable_root_user));
@ -580,6 +612,10 @@ static void
global_defaults()
{
gateway.n_threads = 1;
if (version_string != NULL)
gateway.version_string = strdup(version_string);
else
gateway.version_string = NULL;
}
/**
@ -622,6 +658,7 @@ SERVER *server;
char *user;
char *auth;
char *enable_root_user;
char *version_string;
enable_root_user = config_get_value(obj->parameters, "enable_root_user");
@ -629,6 +666,15 @@ SERVER *server;
"user");
auth = config_get_value(obj->parameters,
"passwd");
version_string = config_get_value(obj->parameters, "version_string");
if (version_string) {
if (service->version_string)
free(service->version_string);
service->version_string = strdup(version_string);
}
if (user && auth) {
service_update(service, router,
user,
@ -861,6 +907,7 @@ static char *service_params[] =
"user",
"passwd",
"enable_root_user",
"version_string",
NULL
};

View File

@ -28,6 +28,7 @@
* 06/02/14 Massimiliano Pinto Added: serviceEnableRootUser routine
* 25/02/14 Massimiliano Pinto Added: service refresh limit feature
* 28/02/14 Massimiliano Pinto users_alloc moved from service_alloc to serviceStartPort (generic hashable for services)
* 07/05/14 Massimiliano Pinto Added: version_string initialized to NULL
*
* @endverbatim
*/
@ -75,6 +76,7 @@ SERVICE *service;
}
service->name = strdup(servname);
service->routerModule = strdup(router);
service->version_string = NULL;
memset(&service->stats, 0, sizeof(SERVICE_STATS));
service->ports = NULL;
service->stats.started = time(0);
@ -159,7 +161,7 @@ GWPROTOCOL *funcs;
if (port->listener->func.listen(port->listener, config_bind)) {
port->listener->session = session_alloc(service, port->listener);
if (port->listener->session != NULL) {
port->listener->session->state = SESSION_STATE_LISTENER;
listeners += 1;

View File

@ -24,8 +24,9 @@
* @verbatim
* Revision History
*
* Date Who Description
* 21/06/13 Mark Riddoch Initial implementation
* Date Who Description
* 21/06/13 Mark Riddoch Initial implementation
* 07/05/14 Massimiliano Pinto Added version_string to global configuration
*
* @endverbatim
*/
@ -54,7 +55,8 @@ typedef struct config_context {
* The gateway global configuration data
*/
typedef struct {
int n_threads; /**< Number of polling threads */
int n_threads; /**< Number of polling threads */
char *version_string; /**< The version string of embedded database library */
} GATEWAY_CONF;
extern int config_load(char *);

View File

@ -1,126 +0,0 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
*
*/
/*
* MYSQL mysql protocol header file
* Revision History
*
* Date Who Description
* 10/06/13 Massimiliano Pinto Initial implementation
*
*/
#include <dcb.h>
/* Protocol packing macros. */
#define gw_mysql_set_byte2(__buffer, __int) do { \
(__buffer)[0]= (uint8_t)((__int) & 0xFF); \
(__buffer)[1]= (uint8_t)(((__int) >> 8) & 0xFF); } while (0)
#define gw_mysql_set_byte3(__buffer, __int) do { \
(__buffer)[0]= (uint8_t)((__int) & 0xFF); \
(__buffer)[1]= (uint8_t)(((__int) >> 8) & 0xFF); \
(__buffer)[2]= (uint8_t)(((__int) >> 16) & 0xFF); } while (0)
#define gw_mysql_set_byte4(__buffer, __int) do { \
(__buffer)[0]= (uint8_t)((__int) & 0xFF); \
(__buffer)[1]= (uint8_t)(((__int) >> 8) & 0xFF); \
(__buffer)[2]= (uint8_t)(((__int) >> 16) & 0xFF); \
(__buffer)[3]= (uint8_t)(((__int) >> 24) & 0xFF); } while (0)
/* Protocol unpacking macros. */
#define gw_mysql_get_byte2(__buffer) \
(uint16_t)((__buffer)[0] | \
((__buffer)[1] << 8))
#define gw_mysql_get_byte3(__buffer) \
(uint32_t)((__buffer)[0] | \
((__buffer)[1] << 8) | \
((__buffer)[2] << 16))
#define gw_mysql_get_byte4(__buffer) \
(uint32_t)((__buffer)[0] | \
((__buffer)[1] << 8) | \
((__buffer)[2] << 16) | \
((__buffer)[3] << 24))
#define gw_mysql_get_byte8(__buffer) \
((uint64_t)(__buffer)[0] | \
((uint64_t)(__buffer)[1] << 8) | \
((uint64_t)(__buffer)[2] << 16) | \
((uint64_t)(__buffer)[3] << 24) | \
((uint64_t)(__buffer)[4] << 32) | \
((uint64_t)(__buffer)[5] << 40) | \
((uint64_t)(__buffer)[6] << 48) | \
((uint64_t)(__buffer)[7] << 56))
typedef enum
{
GW_MYSQL_CAPABILITIES_NONE= 0,
GW_MYSQL_CAPABILITIES_LONG_PASSWORD= (1 << 0),
GW_MYSQL_CAPABILITIES_FOUND_ROWS= (1 << 1),
GW_MYSQL_CAPABILITIES_LONG_FLAG= (1 << 2),
GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB= (1 << 3),
GW_MYSQL_CAPABILITIES_NO_SCHEMA= (1 << 4),
GW_MYSQL_CAPABILITIES_COMPRESS= (1 << 5),
GW_MYSQL_CAPABILITIES_ODBC= (1 << 6),
GW_MYSQL_CAPABILITIES_LOCAL_FILES= (1 << 7),
GW_MYSQL_CAPABILITIES_IGNORE_SPACE= (1 << 8),
GW_MYSQL_CAPABILITIES_PROTOCOL_41= (1 << 9),
GW_MYSQL_CAPABILITIES_INTERACTIVE= (1 << 10),
GW_MYSQL_CAPABILITIES_SSL= (1 << 11),
GW_MYSQL_CAPABILITIES_IGNORE_SIGPIPE= (1 << 12),
GW_MYSQL_CAPABILITIES_TRANSACTIONS= (1 << 13),
GW_MYSQL_CAPABILITIES_RESERVED= (1 << 14),
GW_MYSQL_CAPABILITIES_SECURE_CONNECTION= (1 << 15),
GW_MYSQL_CAPABILITIES_MULTI_STATEMENTS= (1 << 16),
GW_MYSQL_CAPABILITIES_MULTI_RESULTS= (1 << 17),
GW_MYSQL_CAPABILITIES_PS_MULTI_RESULTS= (1 << 18),
GW_MYSQL_CAPABILITIES_PLUGIN_AUTH= (1 << 19),
GW_MYSQL_CAPABILITIES_SSL_VERIFY_SERVER_CERT= (1 << 30),
GW_MYSQL_CAPABILITIES_REMEMBER_OPTIONS= (1 << 31),
GW_MYSQL_CAPABILITIES_CLIENT= (GW_MYSQL_CAPABILITIES_LONG_PASSWORD |
GW_MYSQL_CAPABILITIES_FOUND_ROWS |
GW_MYSQL_CAPABILITIES_LONG_FLAG |
GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB |
GW_MYSQL_CAPABILITIES_LOCAL_FILES |
GW_MYSQL_CAPABILITIES_PLUGIN_AUTH |
GW_MYSQL_CAPABILITIES_TRANSACTIONS |
GW_MYSQL_CAPABILITIES_PROTOCOL_41 |
GW_MYSQL_CAPABILITIES_MULTI_STATEMENTS |
GW_MYSQL_CAPABILITIES_MULTI_RESULTS |
GW_MYSQL_CAPABILITIES_PS_MULTI_RESULTS |
GW_MYSQL_CAPABILITIES_SECURE_CONNECTION),
GW_MYSQL_CAPABILITIES_CLIENT_COMPRESS= (GW_MYSQL_CAPABILITIES_LONG_PASSWORD |
GW_MYSQL_CAPABILITIES_FOUND_ROWS |
GW_MYSQL_CAPABILITIES_LONG_FLAG |
GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB |
GW_MYSQL_CAPABILITIES_LOCAL_FILES |
GW_MYSQL_CAPABILITIES_PLUGIN_AUTH |
GW_MYSQL_CAPABILITIES_TRANSACTIONS |
GW_MYSQL_CAPABILITIES_PROTOCOL_41 |
GW_MYSQL_CAPABILITIES_MULTI_STATEMENTS |
GW_MYSQL_CAPABILITIES_MULTI_RESULTS |
GW_MYSQL_CAPABILITIES_PS_MULTI_RESULTS |
GW_MYSQL_CAPABILITIES_COMPRESS
),
} gw_mysql_capabilities_t;
#define SMALL_CHUNK 1024
#define MAX_CHUNK SMALL_CHUNK * 8 * 4
#define ToHex(Y) (Y>='0'&&Y<='9'?Y-'0':Y-'A'+10)
extern int mysql_send_ok(DCB *, int, int, const char *);
extern int MySQLSendHandshake(DCB *);

View File

@ -38,6 +38,7 @@
* 23/06/13 Mark Riddoch Added service user and users
* 06/02/14 Massimiliano Pinto Added service flag for root user access
* 25/02/14 Massimiliano Pinto Added service refresh limit feature
* 07/05/14 Massimiliano Pinto Added version_string field to service struct
*
* @endverbatim
*/
@ -108,6 +109,7 @@ typedef struct service {
*router; /**< The router we are using */
void *router_instance;
/**< The router instance for this service */
char *version_string; /** version string for this service listeners */
struct server *databases; /**< The set of servers in the backend */
SERVICE_USER credentials; /**< The cedentials of the service user */
SPINLOCK spin; /**< The service spinlock */

View File

@ -33,6 +33,7 @@
* If current user is authenticated the new users' table will replace the old one
* 28/02/2014 Massimiliano Pinto Added: client IPv4 in dcb->ipv4 and inet_ntop for string representation
* 11/03/2014 Massimiliano Pinto Added: Unix socket support
* 07/05/2014 Massimiliano Pinto Added: specific version string in server handshake
*
*/
@ -225,10 +226,21 @@ MySQLSendHandshake(DCB* dcb)
uint8_t mysql_filler_ten[10];
uint8_t mysql_last_byte = 0x00;
char server_scramble[GW_MYSQL_SCRAMBLE_SIZE + 1]="";
char *version_string;
int len_version_string=0;
MySQLProtocol *protocol = DCB_PROTOCOL(dcb, MySQLProtocol);
GWBUF *buf;
/* get the version string from service property if available*/
if (dcb->service->version_string != NULL) {
version_string = dcb->service->version_string;
len_version_string = strlen(version_string);
} else {
version_string = GW_MYSQL_VERSION;
len_version_string = strlen(GW_MYSQL_VERSION);
}
gw_generate_random_str(server_scramble, GW_MYSQL_SCRAMBLE_SIZE);
// copy back to the caller
@ -245,7 +257,7 @@ MySQLSendHandshake(DCB* dcb)
memcpy(mysql_plugin_data, server_scramble + 8, 12);
mysql_payload_size = sizeof(mysql_protocol_version) + (strlen(GW_MYSQL_VERSION) + 1) + sizeof(mysql_thread_id) + 8 + sizeof(mysql_filler) + sizeof(mysql_server_capabilities_one) + sizeof(mysql_server_language) + sizeof(mysql_server_status) + sizeof(mysql_server_capabilities_two) + sizeof(mysql_scramble_len) + sizeof(mysql_filler_ten) + 12 + sizeof(mysql_last_byte) + strlen("mysql_native_password") + sizeof(mysql_last_byte);
mysql_payload_size = sizeof(mysql_protocol_version) + (len_version_string + 1) + sizeof(mysql_thread_id) + 8 + sizeof(mysql_filler) + sizeof(mysql_server_capabilities_one) + sizeof(mysql_server_language) + sizeof(mysql_server_status) + sizeof(mysql_server_capabilities_two) + sizeof(mysql_scramble_len) + sizeof(mysql_filler_ten) + 12 + sizeof(mysql_last_byte) + strlen("mysql_native_password") + sizeof(mysql_last_byte);
// allocate memory for packet header + payload
if ((buf = gwbuf_alloc(sizeof(mysql_packet_header) + mysql_payload_size)) == NULL)
@ -271,8 +283,9 @@ MySQLSendHandshake(DCB* dcb)
mysql_handshake_payload = mysql_handshake_payload + sizeof(mysql_protocol_version);
// write server version plus 0 filler
strcpy((char *)mysql_handshake_payload, GW_MYSQL_VERSION);
mysql_handshake_payload = mysql_handshake_payload + strlen(GW_MYSQL_VERSION);
strcpy((char *)mysql_handshake_payload, version_string);
mysql_handshake_payload = mysql_handshake_payload + len_version_string;
*mysql_handshake_payload = 0x00;
mysql_handshake_payload++;