Merge branch '2.1' into 2.2
This commit is contained in:
commit
2633ad2fe4
@ -1,4 +1,4 @@
|
||||
# MariaDB MaxScale 2.1.9 Release Notes
|
||||
# MariaDB MaxScale 2.1.9 Release Notes -- 2017-09-25
|
||||
|
||||
Release 2.1.9 is a GA release.
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
set(MAXSCALE_VERSION_MAJOR "2" CACHE STRING "Major version")
|
||||
set(MAXSCALE_VERSION_MINOR "1" CACHE STRING "Minor version")
|
||||
set(MAXSCALE_VERSION_PATCH "9" CACHE STRING "Patch version")
|
||||
set(MAXSCALE_VERSION_PATCH "10" CACHE STRING "Patch version")
|
||||
|
||||
# This should only be incremented if a package is rebuilt
|
||||
set(MAXSCALE_BUILD_NUMBER 1 CACHE STRING "Release number")
|
||||
|
@ -100,8 +100,41 @@ void gw_sha1_2_str(const uint8_t *in, int in_len, const uint8_t *in2, int in2_le
|
||||
int gw_getsockerrno(int fd);
|
||||
char *create_hex_sha1_sha1_passwd(char *passwd);
|
||||
|
||||
/** String formatting functions */
|
||||
/**
|
||||
* Trim leading whitespace from a string.
|
||||
*
|
||||
* @param str String to trim.
|
||||
* @return @c str
|
||||
*
|
||||
* @note If there is leading whitespace, the string is moved so that
|
||||
* the returned pointer is always the same as the one given as
|
||||
* argument.
|
||||
*/
|
||||
char* trim_leading(char* str);
|
||||
|
||||
/**
|
||||
* Trim trailing whitespace from a string.
|
||||
*
|
||||
* @param str String to trim.
|
||||
* @return @c str
|
||||
*
|
||||
* @note The returned pointer is always the same the one given as
|
||||
* argument.
|
||||
*/
|
||||
char* trim_trailing(char* str);
|
||||
|
||||
/**
|
||||
* Trim leading and trailing whitespace from a string.
|
||||
*
|
||||
* @param str String to trim.
|
||||
* @return @c str
|
||||
*
|
||||
* @note If there is leading whitespace, the string is moved so that
|
||||
* the returned pointer is always the same the one given as
|
||||
* argument.
|
||||
*/
|
||||
char* trim(char *str);
|
||||
|
||||
void replace_whitespace(char* str);
|
||||
char* squeeze_whitespace(char* str);
|
||||
bool strip_escape_chars(char*);
|
||||
|
@ -490,6 +490,10 @@ add_test_executable(mxs1418.cpp mxs1418 replication LABELS maxscale REPL_BACKEND
|
||||
# https://jira.mariadb.org/browse/MXS-1295
|
||||
add_test_executable(mxs1295_sp_call.cpp mxs1295_sp_call mxs1295 LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# MXS-1451: Password is not stored with skip_authentication=true
|
||||
# https://jira.mariadb.org/browse/MXS-1451
|
||||
add_test_executable(mxs1451_skip_auth.cpp mxs1451_skip_auth mxs1451_skip_auth LABELS maxscale REPL_BACKEND)
|
||||
|
||||
# 'namedserverfilter' test
|
||||
add_test_executable(namedserverfilter.cpp namedserverfilter namedserverfilter LABELS namedserverfilter LIGHT REPL_BACKEND)
|
||||
|
||||
|
@ -0,0 +1,89 @@
|
||||
[maxscale]
|
||||
threads=###threads###
|
||||
|
||||
[MySQL Monitor]
|
||||
type=monitor
|
||||
module=mysqlmon
|
||||
###repl51###
|
||||
servers=server1,server2,server3,server4
|
||||
user=maxskysql
|
||||
passwd=skysql
|
||||
monitor_interval=1000
|
||||
|
||||
[RW Split Router]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server1,server2,server3,server4
|
||||
user=maxskysql
|
||||
passwd=skysql
|
||||
|
||||
[Read Connection Router Slave]
|
||||
type=service
|
||||
router=readconnroute
|
||||
router_options=slave
|
||||
servers=server1,server2,server3,server4
|
||||
user=maxskysql
|
||||
passwd=skysql
|
||||
|
||||
[Read Connection Router Master]
|
||||
type=service
|
||||
router=readconnroute
|
||||
router_options=master
|
||||
servers=server1,server2,server3,server4
|
||||
user=maxskysql
|
||||
passwd=skysql
|
||||
|
||||
[RW Split Listener]
|
||||
type=listener
|
||||
service=RW Split Router
|
||||
protocol=MySQLClient
|
||||
port=4006
|
||||
authenticator_options=skip_authentication=true
|
||||
|
||||
[Read Connection Listener Slave]
|
||||
type=listener
|
||||
service=Read Connection Router Slave
|
||||
protocol=MySQLClient
|
||||
port=4009
|
||||
authenticator_options=skip_authentication=true
|
||||
|
||||
[Read Connection Listener Master]
|
||||
type=listener
|
||||
service=Read Connection Router Master
|
||||
protocol=MySQLClient
|
||||
port=4008
|
||||
authenticator_options=skip_authentication=true
|
||||
|
||||
[CLI]
|
||||
type=service
|
||||
router=cli
|
||||
|
||||
[CLI Listener]
|
||||
type=listener
|
||||
service=CLI
|
||||
protocol=maxscaled
|
||||
socket=default
|
||||
|
||||
[server1]
|
||||
type=server
|
||||
address=###node_server_IP_1###
|
||||
port=###node_server_port_1###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server2]
|
||||
type=server
|
||||
address=###node_server_IP_2###
|
||||
port=###node_server_port_2###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server3]
|
||||
type=server
|
||||
address=###node_server_IP_3###
|
||||
port=###node_server_port_3###
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server4]
|
||||
type=server
|
||||
address=###node_server_IP_4###
|
||||
port=###node_server_port_4###
|
||||
protocol=MySQLBackend
|
62
maxscale-system-test/mxs1451_skip_auth.cpp
Normal file
62
maxscale-system-test/mxs1451_skip_auth.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* MXS-1451: Password is not stored with skip_authentication=true
|
||||
*
|
||||
* Check that connection through MaxScale work even if authentication is disabled
|
||||
*/
|
||||
|
||||
#include "testconnections.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TestConnections test(argc, argv);
|
||||
|
||||
test.set_timeout(60);
|
||||
test.tprintf("Creating users");
|
||||
test.repl->connect();
|
||||
execute_query(test.repl->nodes[0], "CREATE USER 'auth_test'@'%s' IDENTIFIED BY 'test'", test.maxscale_ip());
|
||||
execute_query(test.repl->nodes[0], "GRANT ALL ON *.* to 'auth_test'@'%s'", test.maxscale_ip());
|
||||
execute_query(test.repl->nodes[0], "CREATE USER 'auth_test_nopw'@'%s'", test.maxscale_ip());
|
||||
execute_query(test.repl->nodes[0], "GRANT ALL ON *.* to 'auth_test_nopw'@'%s'", test.maxscale_ip());
|
||||
test.repl->sync_slaves();
|
||||
test.repl->close_connections();
|
||||
|
||||
test.tprintf("Trying to connect through MaxScale");
|
||||
|
||||
test.set_timeout(60);
|
||||
test.tprintf("... with correct credentials");
|
||||
MYSQL* conn = open_conn_db(test.rwsplit_port, test.maxscale_ip(), "test", "auth_test", "test", false);
|
||||
test.try_query(conn, "SHOW DATABASES");
|
||||
mysql_close(conn);
|
||||
|
||||
test.set_timeout(60);
|
||||
test.tprintf("... without a password");
|
||||
conn = open_conn_db(test.rwsplit_port, test.maxscale_ip(), "test", "auth_test_nopw", "", false);
|
||||
test.try_query(conn, "SHOW DATABASES");
|
||||
mysql_close(conn);
|
||||
|
||||
test.set_timeout(60);
|
||||
test.tprintf("... with wrong password");
|
||||
conn = open_conn_db(test.rwsplit_port, test.maxscale_ip(), "test", "auth_test", "wrong_password", false);
|
||||
test.add_result(mysql_errno(conn) == 0, "Connection with wrong password should fail");
|
||||
mysql_close(conn);
|
||||
|
||||
test.set_timeout(60);
|
||||
test.tprintf("... with a password for user without a password");
|
||||
conn = open_conn_db(test.rwsplit_port, test.maxscale_ip(), "test", "auth_test_nopw", "test", false);
|
||||
test.add_result(mysql_errno(conn) == 0, "Connection with wrong password to user without a password should fail");
|
||||
mysql_close(conn);
|
||||
|
||||
test.tprintf("... with bad credentials");
|
||||
conn = open_conn_db(test.rwsplit_port, test.maxscale_ip(), "test", "wrong_user", "wrong_password", false);
|
||||
test.add_result(mysql_errno(conn) == 0, "Connection with bad credentials should fail");
|
||||
mysql_close(conn);
|
||||
|
||||
test.set_timeout(60);
|
||||
test.tprintf("Dropping users");
|
||||
test.repl->connect();
|
||||
execute_query(test.repl->nodes[0], "DROP USER 'auth_test'@'%s'", test.maxscale_ip());
|
||||
execute_query(test.repl->nodes[0], "DROP USER 'auth_test_nopw'@'%s'", test.maxscale_ip());
|
||||
test.repl->close_connections();
|
||||
|
||||
return test.global_result;
|
||||
}
|
@ -18,6 +18,7 @@ add_executable(test_spinlock testspinlock.cc)
|
||||
add_executable(test_trxcompare testtrxcompare.cc ../../../query_classifier/test/testreader.cc)
|
||||
add_executable(test_trxtracking testtrxtracking.cc)
|
||||
add_executable(test_users testusers.cc)
|
||||
add_executable(test_utils testutils.cc)
|
||||
add_executable(testmaxscalepcre2 testmaxscalepcre2.cc)
|
||||
add_executable(testmodulecmd testmodulecmd.cc)
|
||||
add_executable(testconfig testconfig.cc)
|
||||
@ -44,6 +45,7 @@ target_link_libraries(test_spinlock maxscale-common)
|
||||
target_link_libraries(test_trxcompare maxscale-common)
|
||||
target_link_libraries(test_trxtracking maxscale-common)
|
||||
target_link_libraries(test_users maxscale-common)
|
||||
target_link_libraries(test_utils maxscale-common)
|
||||
target_link_libraries(testmaxscalepcre2 maxscale-common)
|
||||
target_link_libraries(testmodulecmd maxscale-common)
|
||||
target_link_libraries(testconfig maxscale-common)
|
||||
@ -70,6 +72,7 @@ add_test(TestServer test_server)
|
||||
add_test(TestService test_service)
|
||||
add_test(TestSpinlock test_spinlock)
|
||||
add_test(TestUsers test_users)
|
||||
add_test(TestUtils test_utils)
|
||||
add_test(TestModulecmd testmodulecmd)
|
||||
add_test(TestConfig testconfig)
|
||||
add_test(TestTrxTracking test_trxtracking)
|
||||
|
130
server/core/test/testutils.cc
Normal file
130
server/core/test/testutils.cc
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
||||
*
|
||||
* Change Date: 2019-07-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include <maxscale/utils.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
#define TRIM_TCE(zFrom, zTo) { zFrom, zTo }
|
||||
|
||||
struct TRIM_TEST_CASE
|
||||
{
|
||||
const char* zFrom;
|
||||
const char* zTo;
|
||||
};
|
||||
|
||||
TRIM_TEST_CASE trim_testcases[] =
|
||||
{
|
||||
TRIM_TCE("", ""),
|
||||
TRIM_TCE("a", "a"),
|
||||
TRIM_TCE(" a", "a"),
|
||||
TRIM_TCE("a ", "a"),
|
||||
TRIM_TCE(" a ", "a"),
|
||||
TRIM_TCE(" a", "a"),
|
||||
TRIM_TCE("a ", "a"),
|
||||
TRIM_TCE(" a ", "a"),
|
||||
TRIM_TCE(" a b ", "a b"),
|
||||
};
|
||||
|
||||
const int n_trim_testcases = sizeof(trim_testcases) / sizeof(trim_testcases[0]);
|
||||
|
||||
TRIM_TEST_CASE trim_leading_testcases[] =
|
||||
{
|
||||
TRIM_TCE("", ""),
|
||||
TRIM_TCE("a", "a"),
|
||||
TRIM_TCE(" a", "a"),
|
||||
TRIM_TCE("a ", "a "),
|
||||
TRIM_TCE(" a ", "a "),
|
||||
TRIM_TCE(" a", "a"),
|
||||
TRIM_TCE("a ", "a "),
|
||||
TRIM_TCE(" a ", "a "),
|
||||
TRIM_TCE(" a b ", "a b "),
|
||||
};
|
||||
|
||||
const int n_trim_leading_testcases = sizeof(trim_leading_testcases) / sizeof(trim_leading_testcases[0]);
|
||||
|
||||
TRIM_TEST_CASE trim_trailing_testcases[] =
|
||||
{
|
||||
TRIM_TCE("", ""),
|
||||
TRIM_TCE("a", "a"),
|
||||
TRIM_TCE(" a", " a"),
|
||||
TRIM_TCE("a ", "a"),
|
||||
TRIM_TCE(" a ", " a"),
|
||||
TRIM_TCE(" a", " a"),
|
||||
TRIM_TCE("a ", "a"),
|
||||
TRIM_TCE(" a ", " a"),
|
||||
TRIM_TCE(" a b ", " a b"),
|
||||
};
|
||||
|
||||
const int n_trim_trailing_testcases = sizeof(trim_trailing_testcases) / sizeof(trim_trailing_testcases[0]);
|
||||
|
||||
|
||||
int test(TRIM_TEST_CASE* pTest_cases, int n_test_cases, char* (*p)(char*))
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
for (int i = 0; i < n_test_cases; ++i)
|
||||
{
|
||||
const char* zFrom = pTest_cases[i].zFrom;
|
||||
const char* zTo = pTest_cases[i].zTo;
|
||||
|
||||
char copy[strlen(zFrom) + 1];
|
||||
strcpy(copy, zFrom);
|
||||
|
||||
char* z = p(copy);
|
||||
|
||||
if (strcmp(z, zTo) != 0)
|
||||
{
|
||||
++rv;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int test_trim()
|
||||
{
|
||||
cout << "trim()" << endl;
|
||||
return test(trim_testcases, n_trim_testcases, trim);
|
||||
}
|
||||
|
||||
int test_trim_leading()
|
||||
{
|
||||
cout << "trim_leading()" << endl;
|
||||
return test(trim_leading_testcases, n_trim_leading_testcases, trim_leading);
|
||||
}
|
||||
|
||||
int test_trim_trailing()
|
||||
{
|
||||
cout << "trim_trailing()" << endl;
|
||||
return test(trim_trailing_testcases, n_trim_trailing_testcases, trim_trailing);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
rv += test_trim();
|
||||
rv += test_trim_leading();
|
||||
rv += test_trim_trailing();
|
||||
|
||||
return rv;
|
||||
}
|
@ -452,13 +452,24 @@ bool mxs_mkdir_all(const char *path, int mask)
|
||||
return mkdir_all_internal(local_path, (mode_t)mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim leading and trailing whitespace from a string
|
||||
*
|
||||
* @param str String to trim
|
||||
* @return Trimmed string
|
||||
*/
|
||||
char* trim(char *str)
|
||||
char* trim_leading(char* str)
|
||||
{
|
||||
char* ptr = str;
|
||||
|
||||
while (isspace(*ptr))
|
||||
{
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (ptr != str)
|
||||
{
|
||||
memmove(str, ptr, strlen(ptr) + 1);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
char* trim_trailing(char* str)
|
||||
{
|
||||
char* ptr = strchr(str, '\0') - 1;
|
||||
|
||||
@ -472,21 +483,14 @@ char* trim(char *str)
|
||||
*(ptr + 1) = '\0';
|
||||
}
|
||||
|
||||
ptr = str;
|
||||
|
||||
while (isspace(*ptr))
|
||||
{
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (ptr != str)
|
||||
{
|
||||
memmove(str, ptr, strlen(ptr) + 1);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
char* trim(char *str)
|
||||
{
|
||||
return trim_leading(trim_trailing(str));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Replace whitespace with hyphens
|
||||
*
|
||||
|
@ -182,17 +182,25 @@ static int auth_cb(void *data, int columns, char** rows, char** row_names)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int validate_mysql_user(sqlite3 *handle, DCB *dcb, MYSQL_session *session,
|
||||
int validate_mysql_user(MYSQL_AUTH* instance, DCB *dcb, MYSQL_session *session,
|
||||
uint8_t *scramble, size_t scramble_len)
|
||||
{
|
||||
sqlite3 *handle = instance->handle;
|
||||
size_t len = sizeof(mysqlauth_validate_user_query) + strlen(session->user) * 2 +
|
||||
strlen(session->db) * 2 + MYSQL_HOST_MAXLEN + session->auth_token_len * 4 + 1;
|
||||
char sql[len + 1];
|
||||
int rval = MXS_AUTH_FAILED;
|
||||
char *err;
|
||||
|
||||
sprintf(sql, mysqlauth_validate_user_query, session->user, dcb->remote,
|
||||
dcb->remote, session->db, session->db);
|
||||
if (instance->skip_auth)
|
||||
{
|
||||
sprintf(sql, mysqlauth_skip_auth_query, session->user, session->db, session->db);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(sql, mysqlauth_validate_user_query, session->user, dcb->remote,
|
||||
dcb->remote, session->db, session->db);
|
||||
}
|
||||
|
||||
struct user_query_result res = {};
|
||||
|
||||
|
@ -304,19 +304,18 @@ mysql_auth_authenticate(DCB *dcb)
|
||||
|
||||
MYSQL_AUTH *instance = (MYSQL_AUTH*)dcb->listener->auth_instance;
|
||||
MySQLProtocol *protocol = DCB_PROTOCOL(dcb, MySQLProtocol);
|
||||
auth_ret = validate_mysql_user(instance->handle, dcb, client_data,
|
||||
auth_ret = validate_mysql_user(instance, dcb, client_data,
|
||||
protocol->scramble, sizeof(protocol->scramble));
|
||||
|
||||
if (auth_ret != MXS_AUTH_SUCCEEDED &&
|
||||
!instance->skip_auth &&
|
||||
service_refresh_users(dcb->service) == 0)
|
||||
{
|
||||
auth_ret = validate_mysql_user(instance->handle, dcb, client_data,
|
||||
auth_ret = validate_mysql_user(instance, dcb, client_data,
|
||||
protocol->scramble, sizeof(protocol->scramble));
|
||||
}
|
||||
|
||||
/* on successful authentication, set user into dcb field */
|
||||
if (auth_ret == MXS_AUTH_SUCCEEDED || instance->skip_auth)
|
||||
if (auth_ret == MXS_AUTH_SUCCEEDED)
|
||||
{
|
||||
auth_ret = MXS_AUTH_SUCCEEDED;
|
||||
dcb->user = MXS_STRDUP_A(client_data->user);
|
||||
@ -638,7 +637,7 @@ int mysql_auth_reauthenticate(DCB *dcb, const char *user,
|
||||
temp.auth_token_len = token_len;
|
||||
|
||||
MYSQL_AUTH *instance = (MYSQL_AUTH*)dcb->listener->auth_instance;
|
||||
int rc = validate_mysql_user(instance->handle, dcb, &temp, scramble, scramble_len);
|
||||
int rc = validate_mysql_user(instance, dcb, &temp, scramble, scramble_len);
|
||||
|
||||
if (rc == MXS_AUTH_SUCCEEDED)
|
||||
{
|
||||
|
@ -66,6 +66,12 @@ static const char mysqlauth_validate_user_query[] =
|
||||
" WHERE user = '%s' AND ( '%s' = host OR '%s' LIKE host) AND (anydb = '1' OR '%s' = '' OR '%s' LIKE db)"
|
||||
" LIMIT 1";
|
||||
|
||||
/** Query that only checks if there's a matching user */
|
||||
static const char mysqlauth_skip_auth_query[] =
|
||||
"SELECT password FROM " MYSQLAUTH_USERS_TABLE_NAME
|
||||
" WHERE user = '%s' AND (anydb = '1' OR '%s' = '' OR '%s' LIKE db)"
|
||||
" LIMIT 1";
|
||||
|
||||
/** Query that checks that the database exists */
|
||||
static const char mysqlauth_validate_database_query[] =
|
||||
"SELECT * FROM " MYSQLAUTH_DATABASES_TABLE_NAME " WHERE db = '%s' LIMIT 1";
|
||||
@ -181,7 +187,7 @@ int replace_mysql_users(SERV_LISTENER *listener, bool skip_local);
|
||||
/**
|
||||
* @brief Verify the user has access to the database
|
||||
*
|
||||
* @param handle SQLite handle to MySQLAuth user database
|
||||
* @param instance MySQLAuth instance
|
||||
* @param dcb Client DCB
|
||||
* @param session Shared MySQL session
|
||||
* @param scramble The scramble sent to the client in the initial handshake
|
||||
@ -189,7 +195,7 @@ int replace_mysql_users(SERV_LISTENER *listener, bool skip_local);
|
||||
*
|
||||
* @return MXS_AUTH_SUCCEEDED if the user has access to the database
|
||||
*/
|
||||
int validate_mysql_user(sqlite3 *handle, DCB *dcb, MYSQL_session *session,
|
||||
uint8_t *scramble, size_t scramble_len);
|
||||
int validate_mysql_user(MYSQL_AUTH* instance, DCB *dcb, MYSQL_session *session,
|
||||
uint8_t *scramble, size_t scramble_len);
|
||||
|
||||
MXS_END_DECLS
|
||||
|
@ -27,33 +27,35 @@
|
||||
*/
|
||||
#include <maxscale/cdefs.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <telnetd.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <telnetd.h>
|
||||
|
||||
#include <maxscale/alloc.h>
|
||||
#include <maxscale/service.h>
|
||||
#include <maxscale/router.h>
|
||||
#include <maxscale/filter.h>
|
||||
#include <maxscale/modulecmd.h>
|
||||
#include <maxscale/atomic.h>
|
||||
#include <maxscale/server.h>
|
||||
#include <maxscale/spinlock.h>
|
||||
#include <maxscale/buffer.h>
|
||||
#include <maxscale/dcb.h>
|
||||
#include <maxscale/users.h>
|
||||
#include <maxscale/config.h>
|
||||
#include <maxscale/adminusers.h>
|
||||
#include <debugcli.h>
|
||||
#include <maxscale/alloc.h>
|
||||
#include <maxscale/atomic.h>
|
||||
#include <maxscale/buffer.h>
|
||||
#include <maxscale/config.h>
|
||||
#include <maxscale/dcb.h>
|
||||
#include <maxscale/filter.h>
|
||||
#include <maxscale/housekeeper.h>
|
||||
#include <maxscale/maxscale.h>
|
||||
#include <maxscale/version.h>
|
||||
#include <maxscale/log_manager.h>
|
||||
#include <maxscale/maxscale.h>
|
||||
#include <maxscale/modulecmd.h>
|
||||
#include <maxscale/router.h>
|
||||
#include <maxscale/server.h>
|
||||
#include <maxscale/service.h>
|
||||
#include <maxscale/spinlock.h>
|
||||
#include <maxscale/users.h>
|
||||
#include <maxscale/utils.h>
|
||||
#include <maxscale/version.h>
|
||||
#include <maxscale/worker.h>
|
||||
|
||||
#include <debugcli.h>
|
||||
|
||||
#include "../../../core/maxscale/config_runtime.h"
|
||||
#include "../../../core/maxscale/maxscale.h"
|
||||
#include "../../../core/maxscale/modules.h"
|
||||
@ -1906,7 +1908,7 @@ execute_cmd(CLI_SESSION *cli)
|
||||
bool in_space = false;
|
||||
int nskip = 0;
|
||||
|
||||
args[0] = cli->cmdbuf;
|
||||
args[0] = trim_leading(cli->cmdbuf);
|
||||
ptr = args[0];
|
||||
lptr = ptr;
|
||||
i = 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user