From ff8366a54b9d5c2e3357cd3783dad531d017994b Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Fri, 4 Nov 2016 12:52:20 +0200 Subject: [PATCH 1/4] Add custom union for handling both sockaddr_in/sockaddr_in6 structures --- lib/MySQL_Session.cpp | 8 +++----- lib/MySQL_Thread.cpp | 35 +++++++++++++++++++---------------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index bcd82d088..19428d30c 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -10,8 +10,6 @@ #define EXPMARIA -#define BUFLEN 256 - extern const CHARSET_INFO * proxysql_find_charset_name(const char * const name); extern MySQL_Authentication *GloMyAuth; @@ -1778,16 +1776,16 @@ __get_pkts_from_client: default: proxy_debug(PROXY_DEBUG_MYSQL_CONNECTION, 5, "Statuses: WAITING_CLIENT_DATA - STATE_UNKNOWN\n"); { - char buf[BUFLEN]; + char buf[INET6_ADDRSTRLEN]; switch (client_myds->client_addr->sa_family) { case AF_INET: { struct sockaddr_in *ipv4 = (struct sockaddr_in *)client_myds->client_addr; - inet_ntop(client_myds->client_addr->sa_family, &ipv4->sin_addr, buf, BUFLEN); + inet_ntop(client_myds->client_addr->sa_family, &ipv4->sin_addr, buf, INET_ADDRSTRLEN); break; } case AF_INET6: { struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)client_myds->client_addr; - inet_ntop(client_myds->client_addr->sa_family, &ipv6->sin6_addr, buf, BUFLEN); + inet_ntop(client_myds->client_addr->sa_family, &ipv6->sin6_addr, buf, INET6_ADDRSTRLEN); break; } default: diff --git a/lib/MySQL_Thread.cpp b/lib/MySQL_Thread.cpp index c64cbdc3f..b2c786ac7 100644 --- a/lib/MySQL_Thread.cpp +++ b/lib/MySQL_Thread.cpp @@ -10,7 +10,6 @@ MySQL_Session *sess_stopat; #define PROXYSQL_LISTEN_LEN 1024 #define MIN_THREADS_FOR_MAINTENANCE 8 -#define BUFLEN 256 extern Query_Processor *GloQPro; extern MySQL_Authentication *GloMyAuth; @@ -2868,9 +2867,13 @@ void MySQL_Thread::unregister_session_connection_handler(int idx, bool _new) { void MySQL_Thread::listener_handle_new_connection(MySQL_Data_Stream *myds, unsigned int n) { int c; - struct sockaddr *addr=(struct sockaddr *)malloc(sizeof(struct sockaddr)); - socklen_t addrlen=sizeof(struct sockaddr); - memset(addr, 0, sizeof(struct sockaddr)); + union { + struct sockaddr_in in; + struct sockaddr_in6 in6; + } custom_sockaddr; + struct sockaddr *addr=(struct sockaddr *)malloc(sizeof(custom_sockaddr)); + socklen_t addrlen=sizeof(custom_sockaddr); + memset(addr, 0, sizeof(custom_sockaddr)); if (GloMTH->num_threads > 1) { // there are more than 1 thread . We pause for a little bit to avoid all connections to be handled by the same thread #ifdef SO_REUSEPORT @@ -2898,18 +2901,18 @@ void MySQL_Thread::listener_handle_new_connection(MySQL_Data_Stream *myds, unsig switch (sess->client_myds->client_addr->sa_family) { case AF_INET: { struct sockaddr_in *ipv4 = (struct sockaddr_in *)sess->client_myds->client_addr; - char buf[BUFLEN]; - inet_ntop(sess->client_myds->client_addr->sa_family, &ipv4->sin_addr, buf, BUFLEN); - sess->client_myds->addr.addr = strdup(buf); - sess->client_myds->addr.port = htons(ipv4->sin_port); + char buf[INET_ADDRSTRLEN]; + inet_ntop(sess->client_myds->client_addr->sa_family, &ipv4->sin_addr, buf, INET_ADDRSTRLEN); + sess->client_myds->addr.addr = strdup(buf); + sess->client_myds->addr.port = htons(ipv4->sin_port); break; } case AF_INET6: { struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)sess->client_myds->client_addr; - char buf[BUFLEN]; - inet_ntop(sess->client_myds->client_addr->sa_family, &ipv6->sin6_addr, buf, BUFLEN); - sess->client_myds->addr.addr = strdup(buf); - sess->client_myds->addr.port = htons(ipv6->sin6_port); + char buf[INET6_ADDRSTRLEN]; + inet_ntop(sess->client_myds->client_addr->sa_family, &ipv6->sin6_addr, buf, INET6_ADDRSTRLEN); + sess->client_myds->addr.addr = strdup(buf); + sess->client_myds->addr.port = htons(ipv6->sin6_port); break; } default: @@ -3243,7 +3246,7 @@ SQLite3_result * MySQL_Threads_Handler::SQL3_Processlist() { switch (sess->client_myds->client_addr->sa_family) { case AF_INET: { struct sockaddr_in *ipv4 = (struct sockaddr_in *)sess->client_myds->client_addr; - inet_ntop(sess->client_myds->client_addr->sa_family, &ipv4->sin_addr, buf, BUFLEN); + inet_ntop(sess->client_myds->client_addr->sa_family, &ipv4->sin_addr, buf, INET_ADDRSTRLEN); pta[4] = strdup(buf); sprintf(port, "%d", ntohs(ipv4->sin_port)); pta[5] = strdup(port); @@ -3251,7 +3254,7 @@ SQLite3_result * MySQL_Threads_Handler::SQL3_Processlist() { } case AF_INET6: { struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)sess->client_myds->client_addr; - inet_ntop(sess->client_myds->client_addr->sa_family, &ipv6->sin6_addr, buf, BUFLEN); + inet_ntop(sess->client_myds->client_addr->sa_family, &ipv6->sin6_addr, buf, INET6_ADDRSTRLEN); pta[4] = strdup(buf); sprintf(port, "%d", ntohs(ipv6->sin6_port)); pta[5] = strdup(port); @@ -3278,7 +3281,7 @@ SQLite3_result * MySQL_Threads_Handler::SQL3_Processlist() { switch (addr.sa_family) { case AF_INET: { struct sockaddr_in *ipv4 = (struct sockaddr_in *)&addr; - inet_ntop(addr.sa_family, &ipv4->sin_addr, buf, BUFLEN); + inet_ntop(addr.sa_family, &ipv4->sin_addr, buf, INET_ADDRSTRLEN); pta[7] = strdup(buf); sprintf(port, "%d", ntohs(ipv4->sin_port)); pta[8] = strdup(port); @@ -3286,7 +3289,7 @@ SQLite3_result * MySQL_Threads_Handler::SQL3_Processlist() { } case AF_INET6: { struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&addr; - inet_ntop(addr.sa_family, &ipv6->sin6_addr, buf, BUFLEN); + inet_ntop(addr.sa_family, &ipv6->sin6_addr, buf, INET6_ADDRSTRLEN); pta[7] = strdup(buf); sprintf(port, "%d", ntohs(ipv6->sin6_port)); pta[8] = strdup(port); From 3cb6101dd40d678998b871cd90bc7378d5ff9b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Mon, 7 Nov 2016 09:22:30 +0000 Subject: [PATCH 2/4] Validate mysql on mysql_stmt_free_result #779 Calling mysql_stmt_free_result() on a statement without a valid pointer to mysql was leading to a crash --- lib/mysql_connection.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/mysql_connection.cpp b/lib/mysql_connection.cpp index be322edae..89175df7f 100644 --- a/lib/mysql_connection.cpp +++ b/lib/mysql_connection.cpp @@ -1377,7 +1377,9 @@ void MySQL_Connection::async_free_result() { query.stmt_result=NULL; } if (query.stmt) { - mysql_stmt_free_result(query.stmt); + if (query.stmt->mysql) { + mysql_stmt_free_result(query.stmt); + } } if (mysql_result) { mysql_free_result(mysql_result); From 3ed1b7ad4daaa7610ea2fa75ced19b5189a3639e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Mon, 7 Nov 2016 11:00:40 +0000 Subject: [PATCH 3/4] Handle error 1226 on connect #786 --- lib/MySQL_Session.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/MySQL_Session.cpp b/lib/MySQL_Session.cpp index 19428d30c..5faf9ba6d 100644 --- a/lib/MySQL_Session.cpp +++ b/lib/MySQL_Session.cpp @@ -1114,6 +1114,14 @@ bool MySQL_Session::handler_again___status_CONNECTING_SERVER(int *_rc) { //wrong_pass=true; if (myds->connect_retries_on_failure >0 ) { myds->connect_retries_on_failure--; + int myerr=mysql_errno(myconn->mysql); + switch (myerr) { + case 1226: // ER_USER_LIMIT_REACHED , User '%s' has exceeded the '%s' resource (current value: %ld) + goto __exit_handler_again___status_CONNECTING_SERVER_with_err; + break; + default: + break; + } //myds->destroy_MySQL_Connection(); if (mirror) { PROXY_TRACE(); @@ -1121,6 +1129,7 @@ bool MySQL_Session::handler_again___status_CONNECTING_SERVER(int *_rc) { myds->destroy_MySQL_Connection_From_Pool(false); NEXT_IMMEDIATE_NEW(CONNECTING_SERVER); } else { +__exit_handler_again___status_CONNECTING_SERVER_with_err: int myerr=mysql_errno(myconn->mysql); if (myerr) { char sqlstate[10]; From 62480058b4ea5ecb217fb314acc8706cd492f3be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Mon, 7 Nov 2016 11:07:36 +0000 Subject: [PATCH 4/4] Clarification on connect timeout #776 --- lib/mysql_connection.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/mysql_connection.cpp b/lib/mysql_connection.cpp index 89175df7f..9dbb6ddae 100644 --- a/lib/mysql_connection.cpp +++ b/lib/mysql_connection.cpp @@ -591,7 +591,8 @@ handler_again: parent->connect_error(mysql_errno(mysql)); break; case ASYNC_CONNECT_TIMEOUT: - proxy_error("Connect timeout on %s:%d : %llu - %llu = %llu\n", parent->address, parent->port, myds->sess->thread->curtime , myds->wait_until, myds->sess->thread->curtime - myds->wait_until); + //proxy_error("Connect timeout on %s:%d : %llu - %llu = %llu\n", parent->address, parent->port, myds->sess->thread->curtime , myds->wait_until, myds->sess->thread->curtime - myds->wait_until); + proxy_error("Connect timeout on %s:%d : exceeded by %lluus\n", myds->sess->thread->curtime - myds->wait_until); parent->connect_error(mysql_errno(mysql)); break; case ASYNC_CHANGE_USER_START: