Merge branch 'develop' into firewall
This commit is contained in:
@ -192,6 +192,7 @@ int i, cflags = REG_ICASE;
|
||||
|
||||
if (my_instance->match == NULL || my_instance->replace == NULL)
|
||||
{
|
||||
free(my_instance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -386,6 +387,8 @@ regmatch_t match[10];
|
||||
free(orig);
|
||||
return NULL;
|
||||
}
|
||||
free(orig);
|
||||
|
||||
res_size = 2 * length;
|
||||
result = (char *)malloc(res_size);
|
||||
res_length = 0;
|
||||
|
@ -377,7 +377,7 @@ static int gw_read_backend_event(DCB *dcb) {
|
||||
dcb,
|
||||
ERRACT_REPLY_CLIENT,
|
||||
&succp);
|
||||
|
||||
gwbuf_free(errbuf);
|
||||
ss_dassert(!succp);
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
@ -459,7 +459,8 @@ static int gw_read_backend_event(DCB *dcb) {
|
||||
dcb,
|
||||
ERRACT_NEW_CONNECTION,
|
||||
&succp);
|
||||
|
||||
gwbuf_free(errbuf);
|
||||
|
||||
if (!succp)
|
||||
{
|
||||
spinlock_acquire(&session->ses_lock);
|
||||
@ -848,7 +849,8 @@ static int gw_error_backend_event(DCB *dcb)
|
||||
dcb,
|
||||
ERRACT_NEW_CONNECTION,
|
||||
&succp);
|
||||
|
||||
gwbuf_free(errbuf);
|
||||
|
||||
/** There are not required backends available, close session. */
|
||||
if (!succp) {
|
||||
spinlock_acquire(&session->ses_lock);
|
||||
@ -1031,7 +1033,8 @@ gw_backend_hangup(DCB *dcb)
|
||||
ERRACT_NEW_CONNECTION,
|
||||
&succp);
|
||||
|
||||
/** There are not required backends available, close session. */
|
||||
gwbuf_free(errbuf);
|
||||
/** There are no required backends available, close session. */
|
||||
if (!succp)
|
||||
{
|
||||
#if defined(SS_DEBUG)
|
||||
@ -1039,7 +1042,6 @@ gw_backend_hangup(DCB *dcb)
|
||||
LOGFILE_ERROR,
|
||||
"Backend hangup -> closing session.")));
|
||||
#endif
|
||||
|
||||
spinlock_acquire(&session->ses_lock);
|
||||
session->state = SESSION_STATE_STOPPING;
|
||||
spinlock_release(&session->ses_lock);
|
||||
@ -1176,7 +1178,8 @@ static int backend_write_delayqueue(DCB *dcb)
|
||||
dcb,
|
||||
ERRACT_NEW_CONNECTION,
|
||||
&succp);
|
||||
|
||||
gwbuf_free(errbuf);
|
||||
|
||||
if (!succp)
|
||||
{
|
||||
if (session != NULL)
|
||||
@ -1300,15 +1303,34 @@ static int gw_change_user(
|
||||
backend->session->client->remote,
|
||||
password_set,
|
||||
"");
|
||||
if (message == NULL)
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Creating error message failed.")));
|
||||
rv = 0;
|
||||
goto retblock;
|
||||
}
|
||||
/** TODO: Add custom message indicating that retry would probably help */
|
||||
buf = modutil_create_mysql_err_msg(1, 0, 1045, "28000", message);
|
||||
free(message);
|
||||
|
||||
if (buf == NULL)
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Creating buffer for error message failed.")));
|
||||
rv = 0;
|
||||
goto retblock;
|
||||
}
|
||||
/** Set flags that help router to identify session commans reply */
|
||||
gwbuf_set_type(buf, GWBUF_TYPE_MYSQL);
|
||||
gwbuf_set_type(buf, GWBUF_TYPE_SESCMD_RESPONSE);
|
||||
gwbuf_set_type(buf, GWBUF_TYPE_RESPONSE_END);
|
||||
/** Create an incoming event for backend DCB */
|
||||
poll_add_epollin_event_to_dcb(backend, buf);
|
||||
rv = 0;
|
||||
poll_add_epollin_event_to_dcb(backend, gwbuf_clone(buf));
|
||||
gwbuf_free(buf);
|
||||
rv = 1;
|
||||
} else {
|
||||
rv = gw_send_change_user_to_backend(database, username, client_sha1, backend_protocol);
|
||||
/*
|
||||
@ -1318,6 +1340,8 @@ static int gw_change_user(
|
||||
strcpy(current_session->db, database);
|
||||
memcpy(current_session->client_sha1, client_sha1, sizeof(current_session->client_sha1));
|
||||
}
|
||||
|
||||
retblock:
|
||||
gwbuf_free(queue);
|
||||
|
||||
return rv;
|
||||
|
@ -430,7 +430,7 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
|
||||
|
||||
connect_with_db =
|
||||
GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB & gw_mysql_get_byte4(
|
||||
&protocol->client_capabilities);
|
||||
(uint32_t *)&protocol->client_capabilities);
|
||||
/*
|
||||
compress =
|
||||
GW_MYSQL_CAPABILITIES_COMPRESS & gw_mysql_get_byte4(
|
||||
@ -859,6 +859,7 @@ int gw_read_client_event(
|
||||
dcb,
|
||||
ERRACT_REPLY_CLIENT,
|
||||
&succp);
|
||||
gwbuf_free(errbuf);
|
||||
ss_dassert(!succp);
|
||||
|
||||
dcb_close(dcb);
|
||||
@ -1017,7 +1018,7 @@ int gw_MySQLListener(
|
||||
errno,
|
||||
strerror(errno));
|
||||
fprintf(stderr, "* Can't bind to %s\n\n", config_bind);
|
||||
|
||||
close(l_so);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1039,13 +1040,14 @@ int gw_MySQLListener(
|
||||
errno,
|
||||
strerror(errno));
|
||||
fprintf(stderr, "* Can't bind to %s\n\n", config_bind);
|
||||
|
||||
close(l_so);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "* Socket Family %i not supported\n", current_addr->sa_family);
|
||||
close(l_so);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1062,6 +1064,7 @@ int gw_MySQLListener(
|
||||
"\n* Failed to start listening MySQL due error %d, %s\n\n",
|
||||
eno,
|
||||
strerror(eno));
|
||||
close(l_so);
|
||||
return 0;
|
||||
}
|
||||
// assign l_so to dcb
|
||||
@ -1191,8 +1194,8 @@ int gw_MySQLAccept(DCB *listener)
|
||||
strerror(eno))));
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error %d, %s."
|
||||
"Failed to accept new client connection.",
|
||||
"Error : Failed to accept new client "
|
||||
"connection due to %d, %s.",
|
||||
eno,
|
||||
strerror(eno))));
|
||||
rc = 1;
|
||||
@ -1223,9 +1226,9 @@ int gw_MySQLAccept(DCB *listener)
|
||||
if (client_dcb == NULL) {
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"%lu [gw_MySQLAccept] Failed to create "
|
||||
"dcb object for client connection.",
|
||||
pthread_self())));
|
||||
"Error : Failed to create "
|
||||
"DCB object for client connection.")));
|
||||
close(c_sock);
|
||||
rc = 1;
|
||||
goto return_rc;
|
||||
}
|
||||
@ -1327,6 +1330,7 @@ int gw_MySQLAccept(DCB *listener)
|
||||
}
|
||||
#endif
|
||||
return_rc:
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -2111,19 +2111,34 @@ char *create_auth_fail_str(
|
||||
else
|
||||
db_len = 0;
|
||||
|
||||
if (db_len>0)
|
||||
if (db_len > 0)
|
||||
{
|
||||
ferrstr = "Access denied for user '%s'@'%s' (using password: %s) to database '%s'";
|
||||
}
|
||||
else
|
||||
{
|
||||
ferrstr = "Access denied for user '%s'@'%s' (using password: %s)";
|
||||
|
||||
}
|
||||
errstr = (char *)malloc(strlen(username)+strlen(ferrstr)+strlen(hostaddr)+strlen("YES")-6 + db_len + ((db_len > 0) ? (strlen(" to database ") +2) : 0) + 1);
|
||||
|
||||
if (errstr != NULL) {
|
||||
if (db_len>0)
|
||||
sprintf(errstr, ferrstr, username, hostaddr, (*sha1 == '\0' ? "NO" : "YES"), db);
|
||||
else
|
||||
sprintf(errstr, ferrstr, username, hostaddr, (*sha1 == '\0' ? "NO" : "YES"));
|
||||
if (errstr == NULL)
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Memory allocation failed due to %s.",
|
||||
strerror(errno))));
|
||||
goto retblock;
|
||||
}
|
||||
|
||||
if (db_len > 0)
|
||||
{
|
||||
sprintf(errstr, ferrstr, username, hostaddr, (*sha1 == '\0' ? "NO" : "YES"), db);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(errstr, ferrstr, username, hostaddr, (*sha1 == '\0' ? "NO" : "YES"));
|
||||
}
|
||||
|
||||
retblock:
|
||||
return errstr;
|
||||
}
|
||||
|
@ -631,7 +631,7 @@ char *ptr, *lptr;
|
||||
else
|
||||
{
|
||||
i++;
|
||||
if (i >= MAXARGS)
|
||||
if (i >= MAXARGS-1)
|
||||
break;
|
||||
args[i] = ptr + 1;
|
||||
}
|
||||
|
@ -654,7 +654,7 @@ DCB* backend_dcb;
|
||||
* @param instance The router instance
|
||||
* @param router_session The router session returned from the newSession call
|
||||
* @param queue The queue of data buffers to route
|
||||
* @return The number of bytes sent
|
||||
* @return if succeed 1, otherwise 0
|
||||
*/
|
||||
static int
|
||||
routeQuery(ROUTER *instance, void *router_session, GWBUF *queue)
|
||||
@ -697,22 +697,24 @@ routeQuery(ROUTER *instance, void *router_session, GWBUF *queue)
|
||||
"Error : Failed to route MySQL command %d to backend "
|
||||
"server.",
|
||||
mysql_command)));
|
||||
rc = 0;
|
||||
goto return_rc;
|
||||
}
|
||||
|
||||
switch(mysql_command) {
|
||||
case MYSQL_COM_CHANGE_USER:
|
||||
rc = backend_dcb->func.auth(
|
||||
backend_dcb,
|
||||
NULL,
|
||||
backend_dcb->session,
|
||||
queue);
|
||||
break;
|
||||
default:
|
||||
rc = backend_dcb->func.write(backend_dcb, queue);
|
||||
break;
|
||||
|
||||
switch(mysql_command) {
|
||||
case MYSQL_COM_CHANGE_USER:
|
||||
rc = backend_dcb->func.auth(
|
||||
backend_dcb,
|
||||
NULL,
|
||||
backend_dcb->session,
|
||||
queue);
|
||||
break;
|
||||
|
||||
default:
|
||||
rc = backend_dcb->func.write(backend_dcb, queue);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
CHK_PROTOCOL(((MySQLProtocol*)backend_dcb->protocol));
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
@ -813,21 +815,33 @@ clientReply(
|
||||
* @param action The action: REPLY, REPLY_AND_CLOSE, NEW_CONNECTION
|
||||
*
|
||||
*/
|
||||
static void
|
||||
handleError(
|
||||
ROUTER *instance,
|
||||
void *router_session,
|
||||
GWBUF *errbuf,
|
||||
DCB *backend_dcb,
|
||||
error_action_t action,
|
||||
bool *succp)
|
||||
static void handleError(
|
||||
ROUTER *instance,
|
||||
void *router_session,
|
||||
GWBUF *errbuf,
|
||||
DCB *backend_dcb,
|
||||
error_action_t action,
|
||||
bool *succp)
|
||||
|
||||
{
|
||||
DCB *client = NULL;
|
||||
DCB *client_dcb;
|
||||
SESSION *session = backend_dcb->session;
|
||||
client = session->client;
|
||||
session_state_t sesstate;
|
||||
|
||||
spinlock_acquire(&session->ses_lock);
|
||||
sesstate = session->state;
|
||||
client_dcb = session->client;
|
||||
spinlock_release(&session->ses_lock);
|
||||
ss_dassert(client_dcb != NULL);
|
||||
|
||||
if (sesstate == SESSION_STATE_ROUTER_READY)
|
||||
{
|
||||
CHK_DCB(client_dcb);
|
||||
client_dcb->func.write(client_dcb, gwbuf_clone(errbuf));
|
||||
}
|
||||
|
||||
/** false because connection is not available anymore */
|
||||
*succp = false;
|
||||
ss_dassert(client != NULL);
|
||||
}
|
||||
|
||||
/** to be inline'd */
|
||||
|
@ -3829,7 +3829,6 @@ static bool route_session_write(
|
||||
{
|
||||
succp = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
rses_end_locked_router_action(router_cli_ses);
|
||||
@ -3842,6 +3841,12 @@ static bool route_session_write(
|
||||
succp = false;
|
||||
goto return_succp;
|
||||
}
|
||||
|
||||
if (router_cli_ses->rses_nbackends <= 0)
|
||||
{
|
||||
succp = false;
|
||||
goto return_succp;
|
||||
}
|
||||
/**
|
||||
* Additional reference is created to querybuf to
|
||||
* prevent it from being released before properties
|
||||
@ -3909,6 +3914,10 @@ static bool route_session_write(
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
succp = false;
|
||||
}
|
||||
}
|
||||
/** Unlock router session */
|
||||
rses_end_locked_router_action(router_cli_ses);
|
||||
@ -4014,7 +4023,7 @@ static void rwsplit_process_router_options(
|
||||
*
|
||||
* @param instance The router instance
|
||||
* @param router_session The router session
|
||||
* @param message The error message to reply
|
||||
* @param errmsgbuf The error message to reply
|
||||
* @param backend_dcb The backend DCB
|
||||
* @param action The action: REPLY, REPLY_AND_CLOSE, NEW_CONNECTION
|
||||
* @param succp Result of action.
|
||||
@ -4079,114 +4088,104 @@ static void handleError (
|
||||
|
||||
|
||||
static void handle_error_reply_client(
|
||||
SESSION* ses,
|
||||
GWBUF* errmsg)
|
||||
SESSION* ses,
|
||||
GWBUF* errmsg)
|
||||
{
|
||||
session_state_t sesstate;
|
||||
DCB* client_dcb;
|
||||
|
||||
spinlock_acquire(&ses->ses_lock);
|
||||
sesstate = ses->state;
|
||||
client_dcb = ses->client;
|
||||
spinlock_release(&ses->ses_lock);
|
||||
|
||||
if (sesstate == SESSION_STATE_ROUTER_READY)
|
||||
{
|
||||
CHK_DCB(client_dcb);
|
||||
client_dcb->func.write(client_dcb, errmsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((errmsg=gwbuf_consume(errmsg, GWBUF_LENGTH(errmsg))) != NULL)
|
||||
;
|
||||
}
|
||||
session_state_t sesstate;
|
||||
DCB* client_dcb;
|
||||
|
||||
spinlock_acquire(&ses->ses_lock);
|
||||
sesstate = ses->state;
|
||||
client_dcb = ses->client;
|
||||
spinlock_release(&ses->ses_lock);
|
||||
|
||||
if (sesstate == SESSION_STATE_ROUTER_READY)
|
||||
{
|
||||
CHK_DCB(client_dcb);
|
||||
client_dcb->func.write(client_dcb, gwbuf_clone(errmsg));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be called with router lock
|
||||
*/
|
||||
static bool handle_error_new_connection(
|
||||
ROUTER_INSTANCE* inst,
|
||||
ROUTER_CLIENT_SES* rses,
|
||||
DCB* backend_dcb,
|
||||
GWBUF* errmsg)
|
||||
ROUTER_INSTANCE* inst,
|
||||
ROUTER_CLIENT_SES* rses,
|
||||
DCB* backend_dcb,
|
||||
GWBUF* errmsg)
|
||||
{
|
||||
SESSION* ses;
|
||||
int router_nservers;
|
||||
int max_nslaves;
|
||||
int max_slave_rlag;
|
||||
backend_ref_t* bref;
|
||||
bool succp;
|
||||
|
||||
ss_dassert(SPINLOCK_IS_LOCKED(&rses->rses_lock));
|
||||
|
||||
ses = backend_dcb->session;
|
||||
CHK_SESSION(ses);
|
||||
|
||||
bref = get_bref_from_dcb(rses, backend_dcb);
|
||||
|
||||
/** failed DCB has already been replaced */
|
||||
if (bref == NULL)
|
||||
{
|
||||
succp = true;
|
||||
goto return_succp;
|
||||
}
|
||||
/**
|
||||
* Error handler is already called for this DCB because
|
||||
* it's not polling anymore. It can be assumed that
|
||||
* it succeed because rses isn't closed.
|
||||
*/
|
||||
if (backend_dcb->state != DCB_STATE_POLLING)
|
||||
{
|
||||
succp = true;
|
||||
goto return_succp;
|
||||
}
|
||||
|
||||
CHK_BACKEND_REF(bref);
|
||||
|
||||
if (BREF_IS_WAITING_RESULT(bref))
|
||||
{
|
||||
DCB* client_dcb;
|
||||
client_dcb = ses->client;
|
||||
client_dcb->func.write(client_dcb, errmsg);
|
||||
bref_clear_state(bref, BREF_WAITING_RESULT);
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((errmsg=gwbuf_consume(errmsg, GWBUF_LENGTH(errmsg))) != NULL)
|
||||
;
|
||||
}
|
||||
bref_clear_state(bref, BREF_IN_USE);
|
||||
bref_set_state(bref, BREF_CLOSED);
|
||||
/**
|
||||
* Remove callback because this DCB won't be used
|
||||
* unless it is reconnected later, and then the callback
|
||||
* is set again.
|
||||
*/
|
||||
dcb_remove_callback(backend_dcb,
|
||||
DCB_REASON_NOT_RESPONDING,
|
||||
&router_handle_state_switch,
|
||||
(void *)bref);
|
||||
|
||||
router_nservers = router_get_servercount(inst);
|
||||
max_nslaves = rses_get_max_slavecount(rses, router_nservers);
|
||||
max_slave_rlag = rses_get_max_replication_lag(rses);
|
||||
/**
|
||||
* Try to get replacement slave or at least the minimum
|
||||
* number of slave connections for router session.
|
||||
*/
|
||||
succp = select_connect_backend_servers(
|
||||
&rses->rses_master_ref,
|
||||
rses->rses_backend_ref,
|
||||
router_nservers,
|
||||
max_nslaves,
|
||||
max_slave_rlag,
|
||||
rses->rses_config.rw_slave_select_criteria,
|
||||
ses,
|
||||
inst);
|
||||
|
||||
SESSION* ses;
|
||||
int router_nservers;
|
||||
int max_nslaves;
|
||||
int max_slave_rlag;
|
||||
backend_ref_t* bref;
|
||||
bool succp;
|
||||
|
||||
ss_dassert(SPINLOCK_IS_LOCKED(&rses->rses_lock));
|
||||
|
||||
ses = backend_dcb->session;
|
||||
CHK_SESSION(ses);
|
||||
|
||||
bref = get_bref_from_dcb(rses, backend_dcb);
|
||||
|
||||
/** failed DCB has already been replaced */
|
||||
if (bref == NULL)
|
||||
{
|
||||
succp = true;
|
||||
goto return_succp;
|
||||
}
|
||||
/**
|
||||
* Error handler is already called for this DCB because
|
||||
* it's not polling anymore. It can be assumed that
|
||||
* it succeed because rses isn't closed.
|
||||
*/
|
||||
if (backend_dcb->state != DCB_STATE_POLLING)
|
||||
{
|
||||
succp = true;
|
||||
goto return_succp;
|
||||
}
|
||||
|
||||
CHK_BACKEND_REF(bref);
|
||||
|
||||
if (BREF_IS_WAITING_RESULT(bref))
|
||||
{
|
||||
DCB* client_dcb;
|
||||
client_dcb = ses->client;
|
||||
client_dcb->func.write(client_dcb, gwbuf_clone(errmsg));
|
||||
bref_clear_state(bref, BREF_WAITING_RESULT);
|
||||
}
|
||||
bref_clear_state(bref, BREF_IN_USE);
|
||||
bref_set_state(bref, BREF_CLOSED);
|
||||
/**
|
||||
* Remove callback because this DCB won't be used
|
||||
* unless it is reconnected later, and then the callback
|
||||
* is set again.
|
||||
*/
|
||||
dcb_remove_callback(backend_dcb,
|
||||
DCB_REASON_NOT_RESPONDING,
|
||||
&router_handle_state_switch,
|
||||
(void *)bref);
|
||||
|
||||
router_nservers = router_get_servercount(inst);
|
||||
max_nslaves = rses_get_max_slavecount(rses, router_nservers);
|
||||
max_slave_rlag = rses_get_max_replication_lag(rses);
|
||||
/**
|
||||
* Try to get replacement slave or at least the minimum
|
||||
* number of slave connections for router session.
|
||||
*/
|
||||
succp = select_connect_backend_servers(
|
||||
&rses->rses_master_ref,
|
||||
rses->rses_backend_ref,
|
||||
router_nservers,
|
||||
max_nslaves,
|
||||
max_slave_rlag,
|
||||
rses->rses_config.rw_slave_select_criteria,
|
||||
ses,
|
||||
inst);
|
||||
|
||||
return_succp:
|
||||
return succp;
|
||||
return succp;
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user