Merge remote-tracking branch 'origin/develop' into MXS-329
Conflicts: server/core/session.c
This commit is contained in:
@ -113,10 +113,11 @@ SHARED_BUF *sbuf;
|
||||
retblock:
|
||||
if (rval == NULL)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Memory allocation failed due to %s.",
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
@ -182,10 +183,11 @@ GWBUF *rval;
|
||||
if ((rval = (GWBUF *)calloc(1,sizeof(GWBUF))) == NULL)
|
||||
{
|
||||
ss_dassert(rval != NULL);
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Memory allocation failed due to %s.",
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -246,10 +248,11 @@ GWBUF *gwbuf_clone_portion(
|
||||
if ((clonebuf = (GWBUF *)malloc(sizeof(GWBUF))) == NULL)
|
||||
{
|
||||
ss_dassert(clonebuf != NULL);
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Memory allocation failed due to %s.",
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
return NULL;
|
||||
}
|
||||
atomic_add(&buf->sbuf->refcount, 1);
|
||||
@ -500,10 +503,11 @@ void gwbuf_add_buffer_object(
|
||||
|
||||
if (newb == NULL)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Memory allocation failed due to %s.",
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
return;
|
||||
}
|
||||
newb->bo_id = id;
|
||||
@ -590,11 +594,11 @@ BUF_PROPERTY *prop;
|
||||
if ((prop = malloc(sizeof(BUF_PROPERTY))) == NULL)
|
||||
{
|
||||
ss_dassert(prop != NULL);
|
||||
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Memory allocation failed due to %s.",
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
return 0;
|
||||
}
|
||||
prop->name = strdup(name);
|
||||
|
@ -73,7 +73,11 @@
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <pcre.h>
|
||||
#include <dbusers.h>
|
||||
|
||||
/** According to the PCRE manual, this should be a multiple of 3 */
|
||||
#define MAXSCALE_PCRE_BUFSZ 24
|
||||
|
||||
/** Defined in log_manager.cc */
|
||||
extern int lm_enabled_logfiles_bitmask;
|
||||
@ -92,7 +96,7 @@ static void global_defaults();
|
||||
static void feedback_defaults();
|
||||
static void check_config_objects(CONFIG_CONTEXT *context);
|
||||
int config_truth_value(char *str);
|
||||
static int internalService(char *router);
|
||||
bool isInternalService(char *router);
|
||||
int config_get_ifaddr(unsigned char *output);
|
||||
int config_get_release_string(char* release);
|
||||
FEEDBACK_CONF * config_get_feedback_data();
|
||||
@ -125,6 +129,57 @@ char *ptr;
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove extra commas and whitespace from a string. This string is interpreted
|
||||
* as a list of string values separated by commas.
|
||||
* @param strptr String to clean
|
||||
* @return pointer to a new string or NULL if an error occurred
|
||||
*/
|
||||
char* config_clean_string_list(char* str)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
if((tmp = malloc(sizeof(char)*(strlen(str) + 1))) != NULL)
|
||||
{
|
||||
char *ptr;
|
||||
int match[MAXSCALE_PCRE_BUFSZ];
|
||||
pcre* re;
|
||||
const char *re_err;
|
||||
int err_offset,rval;
|
||||
|
||||
|
||||
tmp[0] = '\0';
|
||||
|
||||
if((re = pcre_compile("\\s*+([^,]*[^,\\s])",0,&re_err,&err_offset,NULL)) == NULL)
|
||||
{
|
||||
skygw_log_write(LE,"[%s] Error: Regular expression compilation failed at %d: %s",
|
||||
__FUNCTION__,err_offset,re_err);
|
||||
free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = str;
|
||||
|
||||
while((rval = pcre_exec(re,NULL,ptr,strlen(ptr),0,0,(int*)&match,MAXSCALE_PCRE_BUFSZ)) > 1)
|
||||
{
|
||||
const char* substr;
|
||||
|
||||
pcre_get_substring(ptr,(int*)&match,rval,1,&substr);
|
||||
if(strlen(tmp) > 0)
|
||||
strcat(tmp,",");
|
||||
strcat(tmp,substr);
|
||||
pcre_free_substring(substr);
|
||||
ptr = &ptr[match[1]];
|
||||
}
|
||||
pcre_free(re);
|
||||
}
|
||||
else
|
||||
{
|
||||
skygw_log_write(LE,"[%s] Error: Memory allocation failed.",__FUNCTION__);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
/**
|
||||
* Config item handler for the ini file reader
|
||||
*
|
||||
@ -174,12 +229,24 @@ CONFIG_PARAMETER *param, *p1;
|
||||
{
|
||||
if (!strcmp(p1->name, name))
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Configuration object '%s' has multiple "
|
||||
"parameters names '%s'.",
|
||||
ptr->object, name)));
|
||||
return 0;
|
||||
char *tmp;
|
||||
int paramlen = strlen(p1->value) + strlen(value) + 2;
|
||||
|
||||
if((tmp = realloc(p1->value,sizeof(char) * (paramlen))) == NULL)
|
||||
{
|
||||
skygw_log_write(LE,"[%s] Error: Memory allocation failed.",__FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
strcat(tmp,",");
|
||||
strcat(tmp,value);
|
||||
if((p1->value = config_clean_string_list(tmp)) == NULL)
|
||||
{
|
||||
p1->value = tmp;
|
||||
skygw_log_write(LE,"[%s] Error: Cleaning configuration parameter failed.",__FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
free(tmp);
|
||||
return 1;
|
||||
}
|
||||
p1 = p1->next;
|
||||
}
|
||||
@ -205,7 +272,7 @@ int
|
||||
config_load(char *file)
|
||||
{
|
||||
CONFIG_CONTEXT config;
|
||||
int rval;
|
||||
int rval, ini_rval;
|
||||
|
||||
MYSQL *conn;
|
||||
conn = mysql_init(NULL);
|
||||
@ -248,8 +315,23 @@ int rval;
|
||||
config.object = "";
|
||||
config.next = NULL;
|
||||
|
||||
if (ini_parse(file, handler, &config) < 0)
|
||||
if (( ini_rval = ini_parse(file, handler, &config)) != 0)
|
||||
{
|
||||
char errorbuffer[1024 + 1];
|
||||
|
||||
if (ini_rval > 0)
|
||||
snprintf(errorbuffer, sizeof(errorbuffer),
|
||||
"Error: Failed to parse configuration file. Error on line %d.", ini_rval);
|
||||
else if(ini_rval == -1)
|
||||
snprintf(errorbuffer, sizeof(errorbuffer),
|
||||
"Error: Failed to parse configuration file. Failed to open file.");
|
||||
else
|
||||
snprintf(errorbuffer, sizeof(errorbuffer),
|
||||
"Error: Failed to parse configuration file. Memory allocation failed.");
|
||||
|
||||
skygw_log_write(LE, errorbuffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
config_file = file;
|
||||
|
||||
@ -898,7 +980,7 @@ process_config_context(CONFIG_CONTEXT *context)
|
||||
s = strtok_r(NULL, ",", &lasts);
|
||||
}
|
||||
}
|
||||
else if (servers == NULL && internalService(router) == 0)
|
||||
else if (servers == NULL && !isInternalService(router))
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
@ -1107,6 +1189,7 @@ process_config_context(CONFIG_CONTEXT *context)
|
||||
monitorAddUser(obj->element,
|
||||
user,
|
||||
passwd);
|
||||
check_monitor_permissions(obj->element);
|
||||
}
|
||||
else if (obj->element && user)
|
||||
{
|
||||
@ -1460,6 +1543,33 @@ int i;
|
||||
{
|
||||
skygw_set_highp(config_truth_value((char*)value));
|
||||
}
|
||||
else if (strcmp(name, "auth_connect_timeout") == 0)
|
||||
{
|
||||
char* endptr;
|
||||
int intval = strtol(value, &endptr, 0);
|
||||
if(*endptr == '\0' && intval > 0)
|
||||
gateway.auth_conn_timeout = intval;
|
||||
else
|
||||
skygw_log_write(LE, "Invalid timeout value for 'auth_connect_timeout': %s", value);
|
||||
}
|
||||
else if (strcmp(name, "auth_read_timeout") == 0)
|
||||
{
|
||||
char* endptr;
|
||||
int intval = strtol(value, &endptr, 0);
|
||||
if(*endptr == '\0' && intval > 0)
|
||||
gateway.auth_read_timeout = intval;
|
||||
else
|
||||
skygw_log_write(LE, "Invalid timeout value for 'auth_read_timeout': %s", value);
|
||||
}
|
||||
else if (strcmp(name, "auth_write_timeout") == 0)
|
||||
{
|
||||
char* endptr;
|
||||
int intval = strtol(value, &endptr, 0);
|
||||
if(*endptr == '\0' && intval > 0)
|
||||
gateway.auth_write_timeout = intval;
|
||||
else
|
||||
skygw_log_write(LE, "Invalid timeout value for 'auth_write_timeout': %s", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; lognames[i].logname; i++)
|
||||
@ -1525,6 +1635,9 @@ global_defaults()
|
||||
gateway.n_threads = 1;
|
||||
gateway.n_nbpoll = DEFAULT_NBPOLLS;
|
||||
gateway.pollsleep = DEFAULT_POLLSLEEP;
|
||||
gateway.auth_conn_timeout = DEFAULT_AUTH_CONNECT_TIMEOUT;
|
||||
gateway.auth_read_timeout = DEFAULT_AUTH_READ_TIMEOUT;
|
||||
gateway.auth_write_timeout = DEFAULT_AUTH_WRITE_TIMEOUT;
|
||||
if (version_string != NULL)
|
||||
gateway.version_string = strdup(version_string);
|
||||
else
|
||||
@ -2217,9 +2330,11 @@ config_percentage_value(char *str)
|
||||
}
|
||||
|
||||
static char *InternalRouters[] = {
|
||||
"debugcli",
|
||||
"cli",
|
||||
NULL
|
||||
"debugcli",
|
||||
"cli",
|
||||
"maxinfo",
|
||||
"binlogrouter",
|
||||
NULL
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2229,18 +2344,16 @@ static char *InternalRouters[] = {
|
||||
* @param router The router name
|
||||
* @return Non-zero if the router is in the InternalRouters table
|
||||
*/
|
||||
static int
|
||||
internalService(char *router)
|
||||
bool
|
||||
isInternalService(char *router)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (router)
|
||||
{
|
||||
for (i = 0; InternalRouters[i]; i++)
|
||||
for (int i = 0; InternalRouters[i]; i++)
|
||||
if (strcmp(router, InternalRouters[i]) == 0)
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Get the MAC address of first network interface
|
||||
|
@ -52,11 +52,6 @@
|
||||
#include <mysqld_error.h>
|
||||
#include <regex.h>
|
||||
|
||||
|
||||
#define DEFAULT_CONNECT_TIMEOUT 3
|
||||
#define DEFAULT_READ_TIMEOUT 1
|
||||
#define DEFAULT_WRITE_TIMEOUT 2
|
||||
|
||||
#define USERS_QUERY_NO_ROOT " AND user NOT IN ('root')"
|
||||
|
||||
#if 0
|
||||
@ -82,7 +77,7 @@
|
||||
#define MYSQL_USERS_COUNT "SELECT COUNT(1) AS nusers FROM mysql.user"
|
||||
|
||||
#define MYSQL_USERS_WITH_DB_ORDER " ORDER BY host DESC"
|
||||
#define LOAD_MYSQL_USERS_WITH_DB_QUERY "SELECT user.user AS user,user.host AS host,user.password AS password,concat(user.user,user.host,user.password,user.Select_priv,IFNULL(db,'')) AS userdata, user.Select_priv AS anydb,db.db AS db FROM mysql.user LEFT JOIN mysql.db ON user.user=db.user AND user.host=db.host WHERE user.user IS NOT NULL AND user.user <> ''" MYSQL_USERS_WITH_DB_ORDER
|
||||
#define LOAD_MYSQL_USERS_WITH_DB_QUERY "SELECT user.user AS user,user.host AS host,user.password AS password,concat(user.user,user.host,user.password,user.Select_priv,IFNULL(db,'')) AS userdata, user.Select_priv AS anydb,db.db AS db FROM mysql.user LEFT JOIN mysql.db ON user.user=db.user AND user.host=db.host WHERE user.user IS NOT NULL" MYSQL_USERS_WITH_DB_ORDER
|
||||
|
||||
#define MYSQL_USERS_WITH_DB_COUNT "SELECT COUNT(1) AS nusers_db FROM (" LOAD_MYSQL_USERS_WITH_DB_QUERY ") AS tbl_count"
|
||||
|
||||
@ -121,11 +116,7 @@ int add_wildcard_users(USERS *users,
|
||||
char* db,
|
||||
HASHTABLE* hash);
|
||||
|
||||
static int gw_mysql_set_timeouts(
|
||||
MYSQL* handle,
|
||||
int read_timeout,
|
||||
int write_timeout,
|
||||
int connect_timeout);
|
||||
static int gw_mysql_set_timeouts(MYSQL* handle);
|
||||
|
||||
/**
|
||||
* Load the user/passwd form mysql.user table into the service users' hashtable
|
||||
@ -584,7 +575,8 @@ getAllUsers(SERVICE *service, USERS *users)
|
||||
MYSQL_DATABASE_MAXLEN;
|
||||
int dbnames = 0;
|
||||
int db_grants = 0;
|
||||
|
||||
bool anon_user = false;
|
||||
|
||||
if (serviceGetUser(service, &service_user, &service_passwd) == 0)
|
||||
{
|
||||
ss_dassert(service_passwd == NULL || service_user == NULL);
|
||||
@ -629,10 +621,7 @@ getAllUsers(SERVICE *service, USERS *users)
|
||||
}
|
||||
|
||||
/** Set read, write and connect timeout values */
|
||||
if (gw_mysql_set_timeouts(con,
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
DEFAULT_WRITE_TIMEOUT,
|
||||
DEFAULT_CONNECT_TIMEOUT))
|
||||
if (gw_mysql_set_timeouts(con))
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
@ -701,10 +690,7 @@ getAllUsers(SERVICE *service, USERS *users)
|
||||
}
|
||||
|
||||
/** Set read, write and connect timeout values */
|
||||
if (gw_mysql_set_timeouts(con,
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
DEFAULT_WRITE_TIMEOUT,
|
||||
DEFAULT_CONNECT_TIMEOUT))
|
||||
if (gw_mysql_set_timeouts(con))
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
@ -906,12 +892,13 @@ getAllUsers(SERVICE *service, USERS *users)
|
||||
users_data = (char *)calloc(nusers, (users_data_row_len * sizeof(char)) + 1);
|
||||
|
||||
if (users_data == NULL) {
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Memory allocation for user data failed due to "
|
||||
"Error : Memory allocation for user data failed due to "
|
||||
"%d, %s.",
|
||||
errno,
|
||||
strerror(errno))));
|
||||
errno,
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
mysql_free_result(result);
|
||||
mysql_close(con);
|
||||
|
||||
@ -928,7 +915,16 @@ getAllUsers(SERVICE *service, USERS *users)
|
||||
|
||||
int rc = 0;
|
||||
char *password = NULL;
|
||||
|
||||
|
||||
/** If the username is empty, the backend server still has anonymous
|
||||
* user in it. This will mean that localhost addresses do not match
|
||||
* the wildcard host '%' */
|
||||
if(strlen(row[0]) == 0)
|
||||
{
|
||||
anon_user = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (row[2] != NULL) {
|
||||
/* detect mysql_old_password (pre 4.1 protocol) */
|
||||
if (strlen(row[2]) == 16) {
|
||||
@ -1077,7 +1073,10 @@ getAllUsers(SERVICE *service, USERS *users)
|
||||
SHA1((const unsigned char *) final_data, strlen(final_data), hash);
|
||||
|
||||
memcpy(users->cksum, hash, SHA_DIGEST_LENGTH);
|
||||
|
||||
|
||||
/** Set the parameter if it is not configured by the user */
|
||||
if(service->localhost_match_wildcard_host == SERVICE_PARAM_UNINIT)
|
||||
service->localhost_match_wildcard_host = anon_user ? 0 : 1;
|
||||
cleanup:
|
||||
|
||||
free(dpwd);
|
||||
@ -1119,6 +1118,7 @@ getUsers(SERVICE *service, USERS *users)
|
||||
int dbnames = 0;
|
||||
int db_grants = 0;
|
||||
char dbnm[MYSQL_DATABASE_MAXLEN+1];
|
||||
bool anon_user = false;
|
||||
|
||||
if (serviceGetUser(service, &service_user, &service_passwd) == 0)
|
||||
{
|
||||
@ -1141,10 +1141,7 @@ getUsers(SERVICE *service, USERS *users)
|
||||
return -1;
|
||||
}
|
||||
/** Set read, write and connect timeout values */
|
||||
if (gw_mysql_set_timeouts(con,
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
DEFAULT_WRITE_TIMEOUT,
|
||||
DEFAULT_CONNECT_TIMEOUT))
|
||||
if (gw_mysql_set_timeouts(con))
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
@ -1402,12 +1399,13 @@ getUsers(SERVICE *service, USERS *users)
|
||||
users_data = (char *)calloc(nusers, (users_data_row_len * sizeof(char)) + 1);
|
||||
|
||||
if (users_data == NULL) {
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Memory allocation for user data failed due to "
|
||||
"%d, %s.",
|
||||
errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
mysql_free_result(result);
|
||||
mysql_close(con);
|
||||
|
||||
@ -1438,6 +1436,15 @@ getUsers(SERVICE *service, USERS *users)
|
||||
int rc = 0;
|
||||
char *password = NULL;
|
||||
|
||||
/** If the username is empty, the backend server still has anonymous
|
||||
* user in it. This will mean that localhost addresses do not match
|
||||
* the wildcard host '%' */
|
||||
if(strlen(row[0]) == 0)
|
||||
{
|
||||
anon_user = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (row[2] != NULL) {
|
||||
/* detect mysql_old_password (pre 4.1 protocol) */
|
||||
if (strlen(row[2]) == 16) {
|
||||
@ -1568,6 +1575,10 @@ getUsers(SERVICE *service, USERS *users)
|
||||
|
||||
memcpy(users->cksum, hash, SHA_DIGEST_LENGTH);
|
||||
|
||||
/** Set the parameter if it is not configured by the user */
|
||||
if(service->localhost_match_wildcard_host == SERVICE_PARAM_UNINIT)
|
||||
service->localhost_match_wildcard_host = anon_user ? 0 : 1;
|
||||
|
||||
free(users_data);
|
||||
mysql_free_result(result);
|
||||
mysql_close(con);
|
||||
@ -1997,17 +2008,15 @@ int useorig = 0;
|
||||
*
|
||||
* @return 0 if succeed, 1 if failed
|
||||
*/
|
||||
static int gw_mysql_set_timeouts(
|
||||
MYSQL* handle,
|
||||
int read_timeout,
|
||||
int write_timeout,
|
||||
int connect_timeout)
|
||||
static int gw_mysql_set_timeouts(MYSQL* handle)
|
||||
{
|
||||
int rc;
|
||||
|
||||
GATEWAY_CONF* cnf = config_get_global_options();
|
||||
|
||||
if ((rc = mysql_options(handle,
|
||||
MYSQL_OPT_READ_TIMEOUT,
|
||||
(void *)&read_timeout)))
|
||||
(void *)&cnf->auth_read_timeout)))
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
@ -2018,7 +2027,7 @@ static int gw_mysql_set_timeouts(
|
||||
|
||||
if ((rc = mysql_options(handle,
|
||||
MYSQL_OPT_CONNECT_TIMEOUT,
|
||||
(void *)&connect_timeout)))
|
||||
(void *)&cnf->auth_conn_timeout)))
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
@ -2029,7 +2038,7 @@ static int gw_mysql_set_timeouts(
|
||||
|
||||
if ((rc = mysql_options(handle,
|
||||
MYSQL_OPT_WRITE_TIMEOUT,
|
||||
(void *)&write_timeout)))
|
||||
(void *)&cnf->auth_write_timeout)))
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
@ -2315,3 +2324,133 @@ int add_wildcard_users(USERS *users, char* name, char* host, char* password, cha
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the service user has all required permissions to operate properly.
|
||||
* this checks for SELECT permissions on mysql.user and mysql.db tables and for
|
||||
* SHOW DATABASES permissions. If permissions are not adequate, an error message
|
||||
* is logged.
|
||||
* @param service Service to inspect
|
||||
* @return True if service permissions are correct. False if one or more permissions
|
||||
* are missing or if an error occurred.
|
||||
*/
|
||||
bool check_service_permissions(SERVICE* service)
|
||||
{
|
||||
MYSQL* mysql;
|
||||
MYSQL_RES* res;
|
||||
char *user,*password,*dpasswd;
|
||||
SERVER_REF* server;
|
||||
int conn_timeout = 1;
|
||||
bool rval = true;
|
||||
|
||||
if(isInternalService(service->routerModule))
|
||||
return true;
|
||||
|
||||
if(service->dbref == NULL)
|
||||
{
|
||||
skygw_log_write(LE,"%s: Error: Service is missing the servers parameter.",service->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
server = service->dbref;
|
||||
|
||||
if (serviceGetUser(service, &user, &password) == 0)
|
||||
{
|
||||
skygw_log_write(LE,
|
||||
"%s: Error: Service is missing the user credentials for authentication.",
|
||||
service->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
dpasswd = decryptPassword(password);
|
||||
|
||||
if((mysql = mysql_init(NULL)) == NULL)
|
||||
{
|
||||
skygw_log_write(LE,"[%s] Error: MySQL connection initialization failed.",__FUNCTION__);
|
||||
free(dpasswd);
|
||||
return false;
|
||||
}
|
||||
|
||||
mysql_options(mysql,MYSQL_OPT_USE_REMOTE_CONNECTION,NULL);
|
||||
mysql_options(mysql,MYSQL_OPT_CONNECT_TIMEOUT,&conn_timeout);
|
||||
/** Connect to the first server. This assumes all servers have identical
|
||||
* user permissions. */
|
||||
|
||||
if(mysql_real_connect(mysql,server->server->name,user,dpasswd,NULL,server->server->port,NULL,0) == NULL)
|
||||
{
|
||||
int my_errno = mysql_errno(mysql);
|
||||
|
||||
skygw_log_write(LE,"%s: Error: Failed to connect to server %s(%s:%d) when"
|
||||
" checking authentication user credentials and permissions: %d %s",
|
||||
service->name,
|
||||
server->server->unique_name,
|
||||
server->server->name,
|
||||
server->server->port,
|
||||
my_errno,
|
||||
mysql_error(mysql));
|
||||
mysql_close(mysql);
|
||||
free(dpasswd);
|
||||
|
||||
/** We don't know enough about user permissions */
|
||||
return my_errno != ER_ACCESS_DENIED_ERROR;
|
||||
}
|
||||
|
||||
if(mysql_query(mysql,"SELECT user, host, password,Select_priv FROM mysql.user limit 1") != 0)
|
||||
{
|
||||
if(mysql_errno(mysql) == ER_TABLEACCESS_DENIED_ERROR)
|
||||
{
|
||||
skygw_log_write(LE,"%s: Error: User '%s' is missing SELECT privileges"
|
||||
" on mysql.user table. MySQL error message: %s",
|
||||
service->name,user,mysql_error(mysql));
|
||||
rval = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
skygw_log_write(LE,"%s: Error: Failed to query from mysql.user table."
|
||||
" MySQL error message: %s",
|
||||
service->name,mysql_error(mysql));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if((res = mysql_use_result(mysql)) == NULL)
|
||||
{
|
||||
skygw_log_write(LE,"%s: Error: Result retrieval failed when checking for"
|
||||
" permissions to the mysql.user table: %s",
|
||||
service->name,mysql_error(mysql));
|
||||
mysql_close(mysql);
|
||||
free(dpasswd);
|
||||
return true;
|
||||
}
|
||||
mysql_free_result(res);
|
||||
}
|
||||
if(mysql_query(mysql,"SELECT user, host, db FROM mysql.db limit 1") != 0)
|
||||
{
|
||||
if(mysql_errno(mysql) == ER_TABLEACCESS_DENIED_ERROR)
|
||||
{
|
||||
skygw_log_write(LE,"%s: Error: User '%s' is missing SELECT privileges on mysql.db table. MySQL error message: %s",
|
||||
service->name,user,mysql_error(mysql));
|
||||
rval = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
skygw_log_write(LE,"%s: Error: Failed to query from mysql.db table. MySQL error message: %s",
|
||||
service->name,mysql_error(mysql));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if((res = mysql_use_result(mysql)) == NULL)
|
||||
{
|
||||
skygw_log_write(LE,"%s: Error: Result retrieval failed when checking for permissions to the mysql.db table: %s",
|
||||
service->name,mysql_error(mysql));
|
||||
}
|
||||
else
|
||||
{
|
||||
mysql_free_result(res);
|
||||
}
|
||||
}
|
||||
mysql_close(mysql);
|
||||
free(dpasswd);
|
||||
return rval;
|
||||
}
|
||||
|
@ -562,6 +562,7 @@ dcb_process_victim_queue(DCB *listofdcb)
|
||||
{
|
||||
int eno = errno;
|
||||
errno = 0;
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"%lu [dcb_process_victim_queue] Error : Failed to close "
|
||||
@ -570,7 +571,7 @@ dcb_process_victim_queue(DCB *listofdcb)
|
||||
dcb->fd,
|
||||
dcb,
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)))));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -805,6 +806,7 @@ int dcb_read(
|
||||
|
||||
if (-1 == ioctl(dcb->fd, FIONREAD, &bytesavailable))
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
/* <editor-fold defaultstate="collapsed" desc=" Error Logging "> */
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
@ -815,7 +817,7 @@ int dcb_read(
|
||||
STRDCBSTATE(dcb->state),
|
||||
dcb->fd,
|
||||
errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
/* </editor-fold> */
|
||||
return -1;
|
||||
}
|
||||
@ -855,6 +857,7 @@ int dcb_read(
|
||||
* This is a fatal error which should cause shutdown.
|
||||
* Todo shutdown if memory allocation fails.
|
||||
*/
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
/* <editor-fold defaultstate="collapsed" desc=" Error Logging "> */
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
@ -864,7 +867,7 @@ int dcb_read(
|
||||
dcb,
|
||||
dcb->fd,
|
||||
errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
/* </editor-fold> */
|
||||
return -1;
|
||||
}
|
||||
@ -875,6 +878,7 @@ int dcb_read(
|
||||
{
|
||||
if (errno != 0 && errno != EAGAIN && errno != EWOULDBLOCK)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
/* <editor-fold defaultstate="collapsed" desc=" Error Logging "> */
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
@ -885,7 +889,7 @@ int dcb_read(
|
||||
STRDCBSTATE(dcb->state),
|
||||
dcb->fd,
|
||||
errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
/* </editor-fold> */
|
||||
}
|
||||
gwbuf_free(buffer);
|
||||
@ -951,6 +955,7 @@ int dcb_read_SSL(
|
||||
pending = SSL_pending(dcb->ssl);
|
||||
if (rc == -1)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : ioctl FIONREAD for dcb %p in "
|
||||
@ -959,7 +964,7 @@ int dcb_read_SSL(
|
||||
STRDCBSTATE(dcb->state),
|
||||
dcb->fd,
|
||||
errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
n = -1;
|
||||
goto return_n;
|
||||
}
|
||||
@ -1012,6 +1017,7 @@ int dcb_read_SSL(
|
||||
* This is a fatal error which should cause shutdown.
|
||||
* Todo shutdown if memory allocation fails.
|
||||
*/
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Failed to allocate read buffer "
|
||||
@ -1019,7 +1025,7 @@ int dcb_read_SSL(
|
||||
dcb,
|
||||
dcb->fd,
|
||||
errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
|
||||
n = -1;
|
||||
goto return_n;
|
||||
@ -1054,6 +1060,7 @@ int dcb_read_SSL(
|
||||
}
|
||||
else
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Read failed, dcb %p in state "
|
||||
@ -1062,7 +1069,7 @@ int dcb_read_SSL(
|
||||
STRDCBSTATE(dcb->state),
|
||||
dcb->fd,
|
||||
ssl_errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
|
||||
if(ssl_errno == SSL_ERROR_SSL ||
|
||||
ssl_errno == SSL_ERROR_SYSCALL)
|
||||
@ -1337,6 +1344,7 @@ dcb_log_write_failure(DCB *dcb, GWBUF *queue, int eno)
|
||||
{
|
||||
if (eno == EPIPE)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [dcb_write] Write to dcb "
|
||||
@ -1347,7 +1355,7 @@ dcb_log_write_failure(DCB *dcb, GWBUF *queue, int eno)
|
||||
STRDCBSTATE(dcb->state),
|
||||
dcb->fd,
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)))));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1357,6 +1365,7 @@ dcb_log_write_failure(DCB *dcb, GWBUF *queue, int eno)
|
||||
eno != EAGAIN &&
|
||||
eno != EWOULDBLOCK)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Write to dcb %p in "
|
||||
@ -1366,7 +1375,7 @@ dcb_log_write_failure(DCB *dcb, GWBUF *queue, int eno)
|
||||
STRDCBSTATE(dcb->state),
|
||||
dcb->fd,
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)))));
|
||||
|
||||
}
|
||||
|
||||
@ -1392,13 +1401,14 @@ dcb_log_write_failure(DCB *dcb, GWBUF *queue, int eno)
|
||||
}
|
||||
if (dolog)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [dcb_write] Writing to %s socket failed due %d, %s.",
|
||||
pthread_self(),
|
||||
dcb_isclient(dcb) ? "client" : "backend server",
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1513,7 +1523,7 @@ static int
|
||||
dcb_write_SSL_error_report (DCB *dcb, int ret)
|
||||
{
|
||||
int ssl_errno;
|
||||
char errbuf[256];
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
ssl_errno = SSL_get_error(dcb->ssl,ret);
|
||||
|
||||
if (LOG_IS_ENABLED(LOGFILE_DEBUG))
|
||||
@ -1573,9 +1583,7 @@ dcb_write_SSL_error_report (DCB *dcb, int ret)
|
||||
{
|
||||
if(ssl_errno == SSL_ERROR_SYSCALL)
|
||||
{
|
||||
strerror_r(errno,errbuf,255);
|
||||
errbuf[255] = '\0';
|
||||
skygw_log_write(LE,"%d:%s",errno,errbuf);
|
||||
skygw_log_write(LE,"%d:%s", errno, strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
}
|
||||
do
|
||||
{
|
||||
@ -1646,6 +1654,7 @@ int above_water;
|
||||
{
|
||||
break;
|
||||
}
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Write to dcb %p "
|
||||
@ -1654,7 +1663,7 @@ int above_water;
|
||||
STRDCBSTATE(dcb->state),
|
||||
dcb->fd,
|
||||
saved_errno,
|
||||
strerror(saved_errno))));
|
||||
strerror_r(saved_errno, errbuf, sizeof(errbuf)))));
|
||||
break;
|
||||
}
|
||||
/*
|
||||
@ -1750,7 +1759,10 @@ dcb_drain_writeq_SSL(DCB *dcb)
|
||||
skygw_log_write(LE,"%s",errbuf);
|
||||
}
|
||||
if(errno != 0)
|
||||
skygw_log_write(LE,"%d:%s",errno,strerror(errno));
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
skygw_log_write(LE,"%d:%s", errno, strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
}
|
||||
break;
|
||||
case SSL_ERROR_ZERO_RETURN:
|
||||
skygw_log_write(LE,"Socket is closed.");
|
||||
|
@ -109,7 +109,7 @@ EXTERNCMD* externcmd_allocate(char* argstr)
|
||||
if(access(cmd->parameters[0],X_OK) != 0)
|
||||
{
|
||||
skygw_log_write(LE,
|
||||
"Error: Cannot execute file: %s",
|
||||
"Error: Cannot execute file '%s'. Missing execution permissions.",
|
||||
cmd->parameters[0]);
|
||||
externcmd_free(cmd);
|
||||
return NULL;
|
||||
@ -147,8 +147,9 @@ int externcmd_execute(EXTERNCMD* cmd)
|
||||
|
||||
if(pid < 0)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
skygw_log_write(LOGFILE_ERROR,"Error: Failed to execute command '%s', fork failed: [%d] %s",
|
||||
cmd->parameters[0],errno,strerror(errno));
|
||||
cmd->parameters[0],errno,strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
rval = -1;
|
||||
}
|
||||
else if(pid == 0)
|
||||
|
@ -349,12 +349,13 @@ DOWNSTREAM *me;
|
||||
}
|
||||
if ((me = (DOWNSTREAM *)calloc(1, sizeof(DOWNSTREAM))) == NULL)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Memory allocation for filter session failed "
|
||||
"due to %d,%s.",
|
||||
errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright MariaDB Corporation Ab 2013-2014
|
||||
* Copyright MariaDB Corporation Ab 2013-2015
|
||||
*
|
||||
*/
|
||||
|
||||
@ -86,6 +86,10 @@
|
||||
#include <ini.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#define STRING_BUFFER_SIZE 1024
|
||||
#define PIDFD_CLOSED -1
|
||||
|
||||
/** for procname */
|
||||
#if !defined(_GNU_SOURCE)
|
||||
@ -139,7 +143,7 @@ static char datadir[PATH_MAX+1] = "";
|
||||
static bool datadir_defined = false; /*< If the datadir was already set */
|
||||
/* The data directory we created for this gateway instance */
|
||||
static char pidfile[PATH_MAX+1] = "";
|
||||
|
||||
static int pidfd = PIDFD_CLOSED;
|
||||
|
||||
/**
|
||||
* exit flag for log flusher.
|
||||
@ -156,6 +160,8 @@ static bool libmysqld_started = FALSE;
|
||||
*/
|
||||
static bool daemon_mode = true;
|
||||
|
||||
static const char* maxscale_commit = MAXSCALE_COMMIT;
|
||||
|
||||
const char *progname = NULL;
|
||||
static struct option long_options[] = {
|
||||
{"homedir", required_argument, 0, 'c'},
|
||||
@ -174,6 +180,7 @@ static struct option long_options[] = {
|
||||
{"user",required_argument,0,'U'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{"help", no_argument, 0, '?'},
|
||||
{"version-full", no_argument, 0, 'V'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
static int cnf_preparser(void* data, const char* section, const char* name, const char* value);
|
||||
@ -181,6 +188,7 @@ static void log_flush_shutdown(void);
|
||||
static void log_flush_cb(void* arg);
|
||||
static int write_pid_file(); /* write MaxScale pidfile */
|
||||
static void unlink_pidfile(void); /* remove pidfile */
|
||||
static void unlock_pidfile();
|
||||
static void libmysqld_done(void);
|
||||
static bool file_write_header(FILE* outfile);
|
||||
static bool file_write_footer(FILE* outfile);
|
||||
@ -207,7 +215,7 @@ static bool resolve_maxscale_conf_fname(
|
||||
|
||||
static char* check_dir_access(char* dirname,bool,bool);
|
||||
static int set_user();
|
||||
|
||||
bool pid_file_exists();
|
||||
/** SSL multi-threading functions and structures */
|
||||
|
||||
static SPINLOCK* ssl_locks;
|
||||
@ -315,9 +323,9 @@ static void sigusr1_handler (int i)
|
||||
static void sigterm_handler (int i) {
|
||||
extern void shutdown_server();
|
||||
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"MaxScale received signal SIGTERM. Exiting.")));
|
||||
"MaxScale received signal SIGTERM. Exiting.");
|
||||
skygw_log_sync_all();
|
||||
shutdown_server();
|
||||
}
|
||||
@ -327,9 +335,9 @@ sigint_handler (int i)
|
||||
{
|
||||
extern void shutdown_server();
|
||||
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"MaxScale received signal SIGINT. Shutting down.")));
|
||||
"MaxScale received signal SIGINT. Shutting down.");
|
||||
skygw_log_sync_all();
|
||||
shutdown_server();
|
||||
fprintf(stderr, "\n\nShutting down MaxScale\n\n");
|
||||
@ -343,10 +351,9 @@ sigchld_handler (int i)
|
||||
|
||||
if((child = wait(&exit_status)) == -1)
|
||||
{
|
||||
char errbuf[512];
|
||||
strerror_r(errno,errbuf,511);
|
||||
errbuf[511] = '\0';
|
||||
skygw_log_write_flush(LE,"Error: failed to wait child process: %d %s",errno,errbuf);
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
skygw_log_write_flush(LE,"Error: failed to wait child process: %d %s",
|
||||
errno,strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -383,12 +390,16 @@ sigfatal_handler (int i)
|
||||
_exit(1);
|
||||
}
|
||||
fatal_handling = 1;
|
||||
GATEWAY_CONF* cnf = config_get_global_options();
|
||||
fprintf(stderr, "\n\nMaxScale "MAXSCALE_VERSION" received fatal signal %d\n", i);
|
||||
|
||||
fprintf(stderr, "\n\nMaxScale received fatal signal %d\n", i);
|
||||
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Fatal: MaxScale received fatal signal %d. Attempting backtrace.", i)));
|
||||
"Fatal: MaxScale "MAXSCALE_VERSION" received fatal signal %d. Attempting backtrace.", i);
|
||||
|
||||
skygw_log_write_flush(LE,"Commit ID: %s System name: %s "
|
||||
"Release string: %s Embedded library version: %s",
|
||||
maxscale_commit, cnf->sysname, cnf->release_string, cnf->version_string);
|
||||
|
||||
{
|
||||
void *addrs[128];
|
||||
@ -397,9 +408,9 @@ sigfatal_handler (int i)
|
||||
|
||||
if (symbols) {
|
||||
for( n = 0; n < count; n++ ) {
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
" %s\n", symbols[n])));
|
||||
" %s\n", symbols[n]);
|
||||
}
|
||||
free(symbols);
|
||||
} else {
|
||||
@ -444,12 +455,13 @@ static int signal_set (int sig, void (*handler)(int)) {
|
||||
{
|
||||
int eno = errno;
|
||||
errno = 0;
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Failed call sigaction() in %s due to %d, %s.",
|
||||
program_invocation_short_name,
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)));
|
||||
rc = 1;
|
||||
}
|
||||
return rc;
|
||||
@ -472,14 +484,14 @@ int ntfw_cb(
|
||||
{
|
||||
int eno = errno;
|
||||
errno = 0;
|
||||
|
||||
LOGIF(LE, (skygw_log_write(
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
skygw_log_write(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Failed to remove the data directory %s of "
|
||||
"MaxScale due to %d, %s.",
|
||||
datadir,
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)));
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@ -773,21 +785,23 @@ static void print_log_n_stderr(
|
||||
char* fpr_end = "\n*\n";
|
||||
|
||||
if (do_log) {
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"%s %s %s %s",
|
||||
log_err,
|
||||
logstr,
|
||||
eno == 0 ? " " : "Error :",
|
||||
eno == 0 ? " " : strerror(eno))));
|
||||
eno == 0 ? " " : strerror_r(eno, errbuf, sizeof(errbuf)));
|
||||
}
|
||||
if (do_stderr) {
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
fprintf(stderr,
|
||||
"%s %s %s %s %s",
|
||||
fpr_err,
|
||||
fprstr,
|
||||
eno == 0 ? " " : "Error :",
|
||||
eno == 0 ? " " : strerror(eno),
|
||||
eno == 0 ? " " : strerror_r(eno, errbuf, sizeof(errbuf)),
|
||||
fpr_end);
|
||||
}
|
||||
}
|
||||
@ -801,6 +815,7 @@ static bool file_is_readable(
|
||||
{
|
||||
int eno = errno;
|
||||
errno = 0;
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
|
||||
if (!daemon_mode)
|
||||
{
|
||||
@ -808,16 +823,16 @@ static bool file_is_readable(
|
||||
"*\n* Warning : Failed to read the configuration "
|
||||
"file %s. %s.\n*\n",
|
||||
absolute_pathname,
|
||||
strerror(eno));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)));
|
||||
}
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Warning : Failed to read the configuration file %s due "
|
||||
"to %d, %s.",
|
||||
absolute_pathname,
|
||||
eno,
|
||||
strerror(eno))));
|
||||
LOGIF(LE,(skygw_log_sync_all()));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)));
|
||||
skygw_log_sync_all();
|
||||
succp = false;
|
||||
}
|
||||
return succp;
|
||||
@ -832,6 +847,7 @@ static bool file_is_writable(
|
||||
{
|
||||
int eno = errno;
|
||||
errno = 0;
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
|
||||
if (!daemon_mode)
|
||||
{
|
||||
@ -840,15 +856,15 @@ static bool file_is_writable(
|
||||
"due %d, %s.\n*\n",
|
||||
absolute_pathname,
|
||||
eno,
|
||||
strerror(eno));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)));
|
||||
}
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : unable to open file %s for write due "
|
||||
"to %d, %s.",
|
||||
absolute_pathname,
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)));
|
||||
succp = false;
|
||||
}
|
||||
return succp;
|
||||
@ -895,21 +911,22 @@ static char* get_expanded_pathname(
|
||||
{
|
||||
int eno = errno;
|
||||
errno = 0;
|
||||
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
|
||||
fprintf(stderr,
|
||||
"*\n* Warning : Failed to read the "
|
||||
"directory %s. %s.\n*\n",
|
||||
relative_path,
|
||||
strerror(eno));
|
||||
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)));
|
||||
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Warning : Failed to read the "
|
||||
"directory %s, due "
|
||||
"to %d, %s.",
|
||||
relative_path,
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)));
|
||||
free(expanded_path);
|
||||
*output_path = NULL;
|
||||
goto return_cnf_file_buf;
|
||||
@ -930,11 +947,12 @@ static char* get_expanded_pathname(
|
||||
if (cnf_file_buf == NULL)
|
||||
{
|
||||
ss_dassert(cnf_file_buf != NULL);
|
||||
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Memory allocation failed due to %s.",
|
||||
strerror(errno))));
|
||||
"Error : Memory allocation failed due to %s.",
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
|
||||
free(expanded_path);
|
||||
expanded_path = NULL;
|
||||
@ -1006,6 +1024,7 @@ static void usage(void)
|
||||
" -s, --syslog=[yes|no] log messages to syslog (default:yes)\n"
|
||||
" -S, --maxscalelog=[yes|no] log messages to MaxScale log (default: yes)\n"
|
||||
" -v, --version print version info and exit\n"
|
||||
" -V, --version-full print full version info and exit\n"
|
||||
" -?, --help show this help\n"
|
||||
, progname);
|
||||
}
|
||||
@ -1046,6 +1065,7 @@ int main(int argc, char **argv)
|
||||
int l;
|
||||
int i;
|
||||
int n;
|
||||
int ini_rval;
|
||||
intptr_t thread_id;
|
||||
int n_threads; /*< number of epoll listener threads */
|
||||
int n_services;
|
||||
@ -1108,7 +1128,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "dc:f:l:vs:S:?L:D:C:B:U:A:P:",
|
||||
while ((opt = getopt_long(argc, argv, "dc:f:l:vVs:S:?L:D:C:B:U:A:P:",
|
||||
long_options, &option_index)) != -1)
|
||||
{
|
||||
bool succp = true;
|
||||
@ -1143,8 +1163,13 @@ int main(int argc, char **argv)
|
||||
|
||||
case 'v':
|
||||
rc = EXIT_SUCCESS;
|
||||
printf("%s\n",MAXSCALE_VERSION);
|
||||
goto return_main;
|
||||
printf("MaxScale %s\n", MAXSCALE_VERSION);
|
||||
goto return_main;
|
||||
|
||||
case 'V':
|
||||
rc = EXIT_SUCCESS;
|
||||
printf("MaxScale %s - %s\n", MAXSCALE_VERSION, maxscale_commit);
|
||||
goto return_main;
|
||||
|
||||
case 'l':
|
||||
if (strncasecmp(optarg, "file", PATH_MAX) == 0)
|
||||
@ -1582,8 +1607,27 @@ int main(int argc, char **argv)
|
||||
goto return_main;
|
||||
}
|
||||
|
||||
if(ini_parse(cnf_file_path,cnf_preparser,NULL) != 0)
|
||||
if((ini_rval = ini_parse(cnf_file_path, cnf_preparser,NULL)) != 0)
|
||||
{
|
||||
char errorbuffer[STRING_BUFFER_SIZE];
|
||||
|
||||
if(ini_rval > 0)
|
||||
snprintf(errorbuffer, sizeof(errorbuffer),
|
||||
"Error: Failed to pre-parse configuration file. Error on line %d.", ini_rval);
|
||||
else if(ini_rval == -1)
|
||||
snprintf(errorbuffer, sizeof(errorbuffer),
|
||||
"Error: Failed to pre-parse configuration file. Failed to open file.");
|
||||
else
|
||||
snprintf(errorbuffer, sizeof(errorbuffer),
|
||||
"Error: Failed to pre-parse configuration file. Memory allocation failed.");
|
||||
|
||||
skygw_log_write(LE, errorbuffer);
|
||||
if(!daemon_mode)
|
||||
{
|
||||
strncat(errorbuffer, "\n", STRING_BUFFER_SIZE);
|
||||
fprintf(stderr, errorbuffer);
|
||||
}
|
||||
|
||||
rc = MAXSCALE_BADCONFIG;
|
||||
goto return_main;
|
||||
}
|
||||
@ -1664,24 +1708,28 @@ int main(int argc, char **argv)
|
||||
* machine.
|
||||
*/
|
||||
|
||||
snprintf(datadir,PATH_MAX,"%s/data",get_datadir());
|
||||
snprintf(datadir,PATH_MAX, "%s", get_datadir());
|
||||
datadir[PATH_MAX] = '\0';
|
||||
if(mkdir(datadir, 0777) != 0){
|
||||
|
||||
if(errno != EEXIST){
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
fprintf(stderr,
|
||||
"Error: Cannot create data directory '%s': %d %s\n",datadir,errno,strerror(errno));
|
||||
"Error: Cannot create data directory '%s': %d %s\n",
|
||||
datadir, errno, strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
goto return_main;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(datadir,PATH_MAX, "%s/data/data%d", get_datadir(), getpid());
|
||||
snprintf(datadir,PATH_MAX, "%s/data%d", get_datadir(), getpid());
|
||||
|
||||
if(mkdir(datadir, 0777) != 0){
|
||||
|
||||
if(errno != EEXIST){
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
fprintf(stderr,
|
||||
"Error: Cannot create data directory '%s': %d %s\n",datadir,errno,strerror(errno));
|
||||
"Error: Cannot create data directory '%s': %d %s\n",
|
||||
datadir, errno, strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
goto return_main;
|
||||
}
|
||||
}
|
||||
@ -1780,7 +1828,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
}
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : mysql_library_init failed. It is a "
|
||||
"mandatory component, required by router services and "
|
||||
@ -1788,7 +1836,7 @@ int main(int argc, char **argv)
|
||||
mysql_errno(NULL),
|
||||
mysql_error(NULL),
|
||||
__FILE__,
|
||||
__LINE__)));
|
||||
__LINE__);
|
||||
rc = MAXSCALE_NOLIBRARY;
|
||||
goto return_main;
|
||||
}
|
||||
@ -1799,11 +1847,11 @@ int main(int argc, char **argv)
|
||||
char* fprerr = "Failed to load MaxScale configuration "
|
||||
"file. Exiting. See the error log for details.";
|
||||
print_log_n_stderr(false, !daemon_mode, fprerr, fprerr, 0);
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Failed to load MaxScale configuration file %s. "
|
||||
"Exiting.",
|
||||
cnf_file_path)));
|
||||
cnf_file_path);
|
||||
rc = MAXSCALE_BADCONFIG;
|
||||
goto return_main;
|
||||
}
|
||||
@ -1816,8 +1864,22 @@ int main(int argc, char **argv)
|
||||
"MaxScale is running in process %i",
|
||||
getpid())));
|
||||
|
||||
/** Check if a MaxScale process is already running */
|
||||
if(pid_file_exists())
|
||||
{
|
||||
/** There is a process with the PID of the maxscale.pid file running.
|
||||
* Assuming that this is an already running MaxScale process, we
|
||||
* should exit with an error code. */
|
||||
rc = MAXSCALE_ALREADYRUNNING;
|
||||
goto return_main;
|
||||
}
|
||||
|
||||
/* Write process pid into MaxScale pidfile */
|
||||
write_pid_file();
|
||||
if(write_pid_file() != 0)
|
||||
{
|
||||
rc = MAXSCALE_ALREADYRUNNING;
|
||||
goto return_main;
|
||||
}
|
||||
|
||||
/* Init MaxScale poll system */
|
||||
poll_init();
|
||||
@ -1922,6 +1984,7 @@ int main(int argc, char **argv)
|
||||
|
||||
unload_all_modules();
|
||||
/* Remove Pidfile */
|
||||
unlock_pidfile();
|
||||
unlink_pidfile();
|
||||
|
||||
return_main:
|
||||
@ -1983,6 +2046,21 @@ static void log_flush_cb(
|
||||
"Finished MaxScale log flusher.")));
|
||||
}
|
||||
|
||||
static void unlock_pidfile()
|
||||
{
|
||||
if(pidfd != PIDFD_CLOSED)
|
||||
{
|
||||
if(flock(pidfd,LOCK_UN|LOCK_NB) != 0)
|
||||
{
|
||||
char logbuf[STRING_BUFFER_SIZE + PATH_MAX];
|
||||
char* logerr = "Failed to unlock PID file '%s'.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pidfile);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
}
|
||||
close(pidfd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink pid file, called at program exit
|
||||
*/
|
||||
@ -1991,15 +2069,141 @@ static void unlink_pidfile(void)
|
||||
if (strlen(pidfile)) {
|
||||
if (unlink(pidfile))
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
fprintf(stderr,
|
||||
"MaxScale failed to remove pidfile %s: error %d, %s\n",
|
||||
pidfile,
|
||||
errno,
|
||||
strerror(errno));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the maxscale.pid file exists and has a valid PID in it. If one has already been
|
||||
* written and a MaxScale process is running, this instance of MaxScale should shut down.
|
||||
* @return True if the conditions for starting MaxScale are not met and false if
|
||||
* no PID file was found or there is no process running with the PID of the maxscale.pid
|
||||
* file. If false is returned, this process should continue normally.
|
||||
*/
|
||||
bool pid_file_exists()
|
||||
{
|
||||
char pathbuf[PATH_MAX+1];
|
||||
char logbuf[STRING_BUFFER_SIZE + PATH_MAX];
|
||||
char pidbuf[STRING_BUFFER_SIZE];
|
||||
pid_t pid;
|
||||
bool lock_failed = false;
|
||||
|
||||
snprintf(pathbuf, PATH_MAX, "%s/maxscale.pid",get_piddir());
|
||||
pathbuf[PATH_MAX] = '\0';
|
||||
|
||||
if(access(pathbuf,F_OK) != 0)
|
||||
return false;
|
||||
|
||||
if(access(pathbuf,R_OK) == 0)
|
||||
{
|
||||
int fd, b;
|
||||
|
||||
if((fd = open(pathbuf, O_RDWR)) == -1)
|
||||
{
|
||||
char* logerr = "Failed to open PID file '%s'.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
return true;
|
||||
}
|
||||
if(flock(fd,LOCK_EX|LOCK_NB))
|
||||
{
|
||||
if(errno != EWOULDBLOCK)
|
||||
{
|
||||
char* logerr = "Failed to lock PID file '%s'.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
lock_failed = true;
|
||||
}
|
||||
|
||||
pidfd = fd;
|
||||
b = read(fd,pidbuf,sizeof(pidbuf));
|
||||
|
||||
if(b == -1)
|
||||
{
|
||||
char* logerr = "Failed to read from PID file '%s'.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
unlock_pidfile();
|
||||
return true;
|
||||
}
|
||||
else if(b == 0)
|
||||
{
|
||||
/** Empty file */
|
||||
char* logerr = "PID file read from '%s'. File was empty.\n"
|
||||
"If the file is the correct PID file and no other MaxScale processes "
|
||||
"are running, please remove it manually and start MaxScale again.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
unlock_pidfile();
|
||||
return true;
|
||||
}
|
||||
|
||||
pidbuf[b < sizeof(pidbuf) ? b : sizeof(pidbuf) - 1] = '\0';
|
||||
pid = strtol(pidbuf,NULL,0);
|
||||
|
||||
if(pid < 1)
|
||||
{
|
||||
/** Bad PID */
|
||||
char* logerr = "PID file read from '%s'. File contents not valid.\n"
|
||||
"If the file is the correct PID file and no other MaxScale processes "
|
||||
"are running, please remove it manually and start MaxScale again.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
unlock_pidfile();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(kill(pid,0) == -1)
|
||||
{
|
||||
if(errno == ESRCH)
|
||||
{
|
||||
/** no such process, old PID file */
|
||||
if(lock_failed)
|
||||
{
|
||||
char* logerr = "Locking the PID file '%s' failed. Read PID from file and no process found with PID %d. "
|
||||
"Confirm that no other process holds the lock on the PID file.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pathbuf,pid);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, 0);
|
||||
close(fd);
|
||||
}
|
||||
return lock_failed;
|
||||
}
|
||||
else
|
||||
{
|
||||
char* logerr = "Failed to check the existence of process %d read from file '%s'";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pid,pathbuf);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
unlock_pidfile();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char* logerr = "MaxScale is already running. Process id: %d. "
|
||||
"Use another location for the PID file to run multiple instances of MaxScale on the same machine.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pid);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, 0);
|
||||
unlock_pidfile();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char* logerr = "Cannot open PID file '%s', no read permissions. "
|
||||
"Please confirm that the user running MaxScale has read permissions on the file.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write process pid into pidfile anc close it
|
||||
* Parameters:
|
||||
@ -2009,33 +2213,58 @@ static void unlink_pidfile(void)
|
||||
*/
|
||||
|
||||
static int write_pid_file() {
|
||||
|
||||
int fd = -1;
|
||||
char logbuf[STRING_BUFFER_SIZE + PATH_MAX];
|
||||
char pidstr[STRING_BUFFER_SIZE];
|
||||
|
||||
snprintf(pidfile, PATH_MAX, "%s/maxscale.pid",get_piddir());
|
||||
|
||||
fd = open(pidfile, O_WRONLY | O_CREAT | O_TRUNC, 0777);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "MaxScale failed to open pidFile %s: error %d, %s\n", pidfile, errno, strerror(errno));
|
||||
return 1;
|
||||
} else {
|
||||
char pidstr[50]="";
|
||||
/* truncate pidfile content */
|
||||
if (ftruncate(fd, 0) == -1) {
|
||||
fprintf(stderr, "MaxScale failed to truncate pidfile %s: error %d, %s\n", pidfile, errno, strerror(errno));
|
||||
if(pidfd == PIDFD_CLOSED)
|
||||
{
|
||||
int fd = -1;
|
||||
|
||||
fd = open(pidfile, O_WRONLY | O_CREAT, 0777);
|
||||
if (fd == -1) {
|
||||
char* logerr = "Failed to open PID file '%s'.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pidfile);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(flock(fd,LOCK_EX|LOCK_NB))
|
||||
{
|
||||
if(errno == EWOULDBLOCK)
|
||||
{
|
||||
snprintf(logbuf,sizeof(logbuf),"Failed to lock PID file '%s', another process is holding a lock on it. "
|
||||
"Please confirm that no other MaxScale process is using the same PID file location.",pidfile);
|
||||
}
|
||||
|
||||
snprintf(pidstr, sizeof(pidstr)-1, "%d", getpid());
|
||||
|
||||
if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
|
||||
fprintf(stderr, "MaxScale failed to write into pidfile %s: error %d, %s\n", pidfile, errno, strerror(errno));
|
||||
/* close file and return */
|
||||
close(fd);
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
snprintf(logbuf,sizeof(logbuf),"Failed to lock PID file '%s'.",pidfile);
|
||||
}
|
||||
|
||||
/* close file */
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
pidfd = fd;
|
||||
}
|
||||
|
||||
/* truncate pidfile content */
|
||||
if (ftruncate(pidfd, 0)) {
|
||||
char* logerr = "MaxScale failed to truncate PID file '%s'.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pidfile);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
unlock_pidfile();
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(pidstr, sizeof(pidstr)-1, "%d", getpid());
|
||||
|
||||
if (pwrite(pidfd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
|
||||
char* logerr = "MaxScale failed to write into PID file '%s'.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pidfile);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
unlock_pidfile();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* success */
|
||||
@ -2208,32 +2437,36 @@ static int set_user(char* user)
|
||||
pwname = getpwnam(user);
|
||||
if(pwname == NULL)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
printf("Error: Failed to retrieve user information for '%s': %d %s\n",
|
||||
user,errno,errno == 0 ? "User not found" : strerror(errno));
|
||||
user,errno,errno == 0 ? "User not found" : strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
rval = setgid(pwname->pw_gid);
|
||||
if(rval != 0)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
printf("Error: Failed to change group to '%d': %d %s\n",
|
||||
pwname->pw_gid,errno,strerror(errno));
|
||||
pwname->pw_gid, errno, strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
return rval;
|
||||
}
|
||||
|
||||
rval = setuid(pwname->pw_uid);
|
||||
if(rval != 0)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
printf("Error: Failed to change user to '%s': %d %s\n",
|
||||
pwname->pw_name,errno,strerror(errno));
|
||||
pwname->pw_name, errno, strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
return rval;
|
||||
}
|
||||
if(prctl(PR_GET_DUMPABLE) == 0)
|
||||
{
|
||||
if(prctl(PR_SET_DUMPABLE ,1) == -1)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
printf("Error: Failed to set dumpable flag on for the process '%s': %d %s\n",
|
||||
pwname->pw_name,errno,strerror(errno));
|
||||
pwname->pw_name, errno, strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +147,8 @@ void gw_daemonize(void) {
|
||||
pid = fork();
|
||||
|
||||
if (pid < 0) {
|
||||
fprintf(stderr, "fork() error %s\n", strerror(errno));
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
fprintf(stderr, "fork() error %s\n", strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -157,7 +158,8 @@ void gw_daemonize(void) {
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
fprintf(stderr, "setsid() error %s\n", strerror(errno));
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
fprintf(stderr, "setsid() error %s\n", strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,8 @@
|
||||
#include <modules.h>
|
||||
#include <skygw_utils.h>
|
||||
#include <log_manager.h>
|
||||
#include <secrets.h>
|
||||
#include <mysql/mysqld_error.h>
|
||||
|
||||
/** Defined in log_manager.cc */
|
||||
extern int lm_enabled_logfiles_bitmask;
|
||||
@ -448,3 +450,80 @@ int *data;
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the monitor user has all required permissions to operate properly.
|
||||
* this checks for REPLICATION CLIENT permissions
|
||||
* @param service Monitor to inspect
|
||||
* @return False if an error with monitor permissions was detected or if an
|
||||
* error occurred. True if permissions are correct.
|
||||
*/
|
||||
bool check_monitor_permissions(MONITOR* monitor)
|
||||
{
|
||||
MYSQL* mysql;
|
||||
MYSQL_RES* res;
|
||||
char *user,*dpasswd;
|
||||
SERVER* server;
|
||||
int conn_timeout = 1;
|
||||
bool rval = true;
|
||||
|
||||
user = monitor->user;
|
||||
dpasswd = decryptPassword(monitor->password);
|
||||
|
||||
if((mysql = mysql_init(NULL)) == NULL)
|
||||
{
|
||||
skygw_log_write(LE,"[%s] Error: MySQL connection initialization failed.",__FUNCTION__);
|
||||
free(dpasswd);
|
||||
return false;
|
||||
}
|
||||
|
||||
server = monitor->databases->server;
|
||||
mysql_options(mysql,MYSQL_OPT_USE_REMOTE_CONNECTION,NULL);
|
||||
mysql_options(mysql,MYSQL_OPT_CONNECT_TIMEOUT,&conn_timeout);
|
||||
|
||||
/** Connect to the first server. This assumes all servers have identical
|
||||
* user permissions. */
|
||||
if(mysql_real_connect(mysql,server->name,user,dpasswd,NULL,server->port,NULL,0) == NULL)
|
||||
{
|
||||
skygw_log_write(LE,"%s: Error: Failed to connect to server %s(%s:%d) when"
|
||||
" checking monitor user credentials and permissions.",
|
||||
monitor->name,
|
||||
server->unique_name,
|
||||
server->name,
|
||||
server->port);
|
||||
mysql_close(mysql);
|
||||
free(dpasswd);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(mysql_query(mysql,"show slave status") != 0)
|
||||
{
|
||||
if(mysql_errno(mysql) == ER_SPECIFIC_ACCESS_DENIED_ERROR)
|
||||
{
|
||||
skygw_log_write(LE,"%s: Error: User '%s' is missing REPLICATION CLIENT privileges. MySQL error message: %s",
|
||||
monitor->name,user,mysql_error(mysql));
|
||||
}
|
||||
else
|
||||
{
|
||||
skygw_log_write(LE,"%s: Error: Monitor failed to query for slave status. MySQL error message: %s",
|
||||
monitor->name,mysql_error(mysql));
|
||||
}
|
||||
rval = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((res = mysql_use_result(mysql)) == NULL)
|
||||
{
|
||||
skygw_log_write(LE,"%s: Error: Result retrieval failed when checking for REPLICATION CLIENT permissions: %s",
|
||||
monitor->name,mysql_error(mysql));
|
||||
rval = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
mysql_free_result(res);
|
||||
}
|
||||
}
|
||||
mysql_close(mysql);
|
||||
free(dpasswd);
|
||||
return rval;
|
||||
}
|
@ -889,6 +889,7 @@ unsigned long qtime;
|
||||
dcb->func.write_ready(dcb);
|
||||
}
|
||||
} else {
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [poll_waitevents] "
|
||||
@ -896,7 +897,7 @@ unsigned long qtime;
|
||||
"dcb %p, fd %i",
|
||||
pthread_self(),
|
||||
eno,
|
||||
strerror(eno),
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)),
|
||||
dcb,
|
||||
dcb->fd)));
|
||||
}
|
||||
@ -949,6 +950,7 @@ unsigned long qtime;
|
||||
#if defined(FAKE_CODE)
|
||||
if (eno == 0) {
|
||||
eno = dcb_fake_write_errno[dcb->fd];
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [poll_waitevents] "
|
||||
@ -956,18 +958,19 @@ unsigned long qtime;
|
||||
"%s",
|
||||
pthread_self(),
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)))));
|
||||
}
|
||||
dcb_fake_write_errno[dcb->fd] = 0;
|
||||
#endif /* FAKE_CODE */
|
||||
if (eno != 0) {
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [poll_waitevents] "
|
||||
"EPOLLERR due %d, %s.",
|
||||
pthread_self(),
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)))));
|
||||
}
|
||||
atomic_add(&pollStats.n_error, 1);
|
||||
/** Read session id to thread's local storage */
|
||||
@ -985,7 +988,7 @@ unsigned long qtime;
|
||||
{
|
||||
int eno = 0;
|
||||
eno = gw_getsockerrno(dcb->fd);
|
||||
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [poll_waitevents] "
|
||||
@ -995,7 +998,7 @@ unsigned long qtime;
|
||||
dcb,
|
||||
dcb->fd,
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)))));
|
||||
atomic_add(&pollStats.n_hup, 1);
|
||||
spinlock_acquire(&dcb->dcb_initlock);
|
||||
if ((dcb->flags & DCBF_HUNG) == 0)
|
||||
@ -1021,7 +1024,7 @@ unsigned long qtime;
|
||||
{
|
||||
int eno = 0;
|
||||
eno = gw_getsockerrno(dcb->fd);
|
||||
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [poll_waitevents] "
|
||||
@ -1031,7 +1034,7 @@ unsigned long qtime;
|
||||
dcb,
|
||||
dcb->fd,
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)))));
|
||||
atomic_add(&pollStats.n_hup, 1);
|
||||
spinlock_acquire(&dcb->dcb_initlock);
|
||||
if ((dcb->flags & DCBF_HUNG) == 0)
|
||||
|
@ -81,24 +81,26 @@ static int reported = 0;
|
||||
{
|
||||
if (!reported)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LM, (skygw_log_write(
|
||||
LOGFILE_MESSAGE,
|
||||
"Encrypted password file %s can't be accessed "
|
||||
"(%s). Password encryption is not used.",
|
||||
secret_file,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)))));
|
||||
reported = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : access for secrets file "
|
||||
"[%s] failed. Error %d, %s.",
|
||||
secret_file,
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)))));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -108,13 +110,14 @@ static int reported = 0;
|
||||
{
|
||||
int eno = errno;
|
||||
errno = 0;
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Failed opening secret "
|
||||
"file [%s]. Error %d, %s.",
|
||||
secret_file,
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)))));
|
||||
return NULL;
|
||||
|
||||
}
|
||||
@ -124,13 +127,14 @@ static int reported = 0;
|
||||
int eno = errno;
|
||||
errno = 0;
|
||||
close(fd);
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : fstat for secret file %s "
|
||||
"failed. Error %d, %s.",
|
||||
secret_file,
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)))));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -139,13 +143,14 @@ static int reported = 0;
|
||||
int eno = errno;
|
||||
errno = 0;
|
||||
close(fd);
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Secrets file %s has "
|
||||
"incorrect size. Error %d, %s.",
|
||||
secret_file,
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)))));
|
||||
return NULL;
|
||||
}
|
||||
if (secret_stats.st_mode != (S_IRUSR|S_IFREG))
|
||||
@ -181,6 +186,7 @@ static int reported = 0;
|
||||
errno = 0;
|
||||
close(fd);
|
||||
free(keys);
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Read from secrets file "
|
||||
@ -189,7 +195,7 @@ static int reported = 0;
|
||||
len,
|
||||
sizeof(MAXKEYS),
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)))));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -198,13 +204,14 @@ static int reported = 0;
|
||||
int eno = errno;
|
||||
errno = 0;
|
||||
free(keys);
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Failed closing the "
|
||||
"secrets file %s. Error %d, %s.",
|
||||
secret_file,
|
||||
eno,
|
||||
strerror(eno))));
|
||||
strerror_r(eno, errbuf, sizeof(errbuf)))));
|
||||
return NULL;
|
||||
}
|
||||
ss_dassert(keys != NULL);
|
||||
@ -239,24 +246,26 @@ if(strlen(path) > PATH_MAX)
|
||||
/* Open for writing | Create | Truncate the file for writing */
|
||||
if ((fd = open(secret_file, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR)) < 0)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : failed opening secret "
|
||||
"file [%s]. Error %d, %s.",
|
||||
secret_file,
|
||||
errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Open for writing | Create | Truncate the file for writing */
|
||||
if ((randfd = open("/dev/random", O_RDONLY)) < 0)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : failed opening /dev/random. Error %d, %s.",
|
||||
errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
@ -278,13 +287,14 @@ if(strlen(path) > PATH_MAX)
|
||||
/* Write data */
|
||||
if (write(fd, &key, sizeof(key)) < 0)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : failed writing into "
|
||||
"secret file [%s]. Error %d, %s.",
|
||||
secret_file,
|
||||
errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
@ -292,24 +302,26 @@ if(strlen(path) > PATH_MAX)
|
||||
/* close file */
|
||||
if (close(fd) < 0)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : failed closing the "
|
||||
"secret file [%s]. Error %d, %s.",
|
||||
secret_file,
|
||||
errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
}
|
||||
|
||||
if( chmod(secret_file, S_IRUSR) < 0)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : failed to change the permissions of the"
|
||||
"secret file [%s]. Error %d, %s.",
|
||||
secret_file,
|
||||
errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -140,6 +140,7 @@ SERVICE *service;
|
||||
service->routerModule = strdup(router);
|
||||
service->users_from_all = false;
|
||||
service->resources = NULL;
|
||||
service->localhost_match_wildcard_host = SERVICE_PARAM_UNINIT;
|
||||
service->ssl_mode = SSL_DISABLED;
|
||||
service->ssl_init_done = false;
|
||||
service->ssl_ca_cert = NULL;
|
||||
@ -234,19 +235,19 @@ GWPROTOCOL *funcs;
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Unable to load users from %s:%d for "
|
||||
"service %s.",
|
||||
"Error : Unable to load users for "
|
||||
"service %s listening at %s:%d.",
|
||||
service->name,
|
||||
(port->address == NULL ? "0.0.0.0" : port->address),
|
||||
port->port,
|
||||
service->name)));
|
||||
port->port)));
|
||||
|
||||
{
|
||||
/* Try loading authentication data from file cache */
|
||||
char *ptr, path[4097];
|
||||
strcpy(path, get_cachedir());
|
||||
strncat(path, "/", 4096);
|
||||
strncat(path, service->name, 4096);
|
||||
strncat(path, "/.cache/dbusers", 4096);
|
||||
char *ptr, path[PATH_MAX+1];
|
||||
strncpy(path, get_cachedir(),sizeof(path)-1);
|
||||
strncat(path, "/", sizeof(path)-1);
|
||||
strncat(path, service->name, sizeof(path)-1);
|
||||
strncat(path, "/.cache/dbusers", sizeof(path)-1);
|
||||
loaded = dbusers_load(service->users, path);
|
||||
if (loaded != -1)
|
||||
{
|
||||
@ -281,10 +282,11 @@ GWPROTOCOL *funcs;
|
||||
{
|
||||
if(errno != EEXIST)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
skygw_log_write(LOGFILE_ERROR,"Error : Failed to create directory '%s': [%d] %s",
|
||||
path,
|
||||
errno,
|
||||
strerror(errno));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
}
|
||||
mkdir_rval = 0;
|
||||
}
|
||||
@ -299,10 +301,11 @@ GWPROTOCOL *funcs;
|
||||
{
|
||||
if(errno != EEXIST)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
skygw_log_write(LOGFILE_ERROR,"Error : Failed to create directory '%s': [%d] %s",
|
||||
path,
|
||||
errno,
|
||||
strerror(errno));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)));
|
||||
}
|
||||
mkdir_rval = 0;
|
||||
}
|
||||
@ -416,6 +419,16 @@ serviceStart(SERVICE *service)
|
||||
SERV_PROTOCOL *port;
|
||||
int listeners = 0;
|
||||
|
||||
|
||||
if(!check_service_permissions(service))
|
||||
{
|
||||
skygw_log_write_flush(LE,
|
||||
"%s: Error: Inadequate user permissions for service. Service not started.",
|
||||
service->name);
|
||||
service->state = SERVICE_STATE_FAILED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(service->ssl_mode != SSL_DISABLED)
|
||||
{
|
||||
if(serviceInitSSL(service) != 0)
|
||||
|
@ -82,12 +82,13 @@ session_alloc(SERVICE *service, DCB *client_dcb)
|
||||
|
||||
if (session == NULL)
|
||||
{
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Failed to allocate memory for "
|
||||
"session object due error %d, %s.",
|
||||
errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
session_simple_free(session, client_dcb);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char
|
||||
}
|
||||
if ((service = (SERVICE *)calloc(1, sizeof(SERVICE))) == NULL) {
|
||||
fprintf(stderr, "service_alloc() failed\n");
|
||||
dcb_free(dcb);
|
||||
dcb_close(dcb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char
|
||||
fprintf(stderr, "Failed adding %s@%s(%lu)\n", username, ret_ip, fix_ipv4);
|
||||
users_free(mysql_users);
|
||||
free(service);
|
||||
dcb_free(dcb);
|
||||
dcb_close(dcb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char
|
||||
|
||||
users_free(mysql_users);
|
||||
free(service);
|
||||
dcb_free(dcb);
|
||||
dcb_close(dcb);
|
||||
|
||||
if (!fetch_data)
|
||||
return 1;
|
||||
@ -198,7 +198,7 @@ int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *pass
|
||||
}
|
||||
if ((service = (SERVICE *)calloc(1, sizeof(SERVICE))) == NULL) {
|
||||
fprintf(stderr, "service_alloc() failed\n");
|
||||
dcb_free(dcb);
|
||||
dcb_close(dcb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -208,7 +208,7 @@ int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *pass
|
||||
if(!setipaddress(&client_addr.sin_addr, from)) {
|
||||
fprintf(stderr, "setipaddress failed for host [%s]\n", from);
|
||||
free(service);
|
||||
dcb_free(dcb);
|
||||
dcb_close(dcb);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -216,7 +216,7 @@ int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *pass
|
||||
if ((data = (MYSQL_session *) calloc(1, sizeof(MYSQL_session))) == NULL) {
|
||||
fprintf(stderr, "MYSQL_session alloc failed\n");
|
||||
free(service);
|
||||
dcb_free(dcb);
|
||||
dcb_close(dcb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -235,7 +235,7 @@ int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *pass
|
||||
else
|
||||
strncpy(data->db, "",MYSQL_DATABASE_MAXLEN);
|
||||
|
||||
/* freed by dcb_free(dcb) */
|
||||
/* freed by dcb_close(dcb) */
|
||||
dcb->data = data;
|
||||
|
||||
// the routine returns 1 on success
|
||||
@ -264,7 +264,7 @@ int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *pass
|
||||
|
||||
users_free(mysql_users);
|
||||
free(service);
|
||||
dcb_free(dcb);
|
||||
dcb_close(dcb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <housekeeper.h>
|
||||
#include <buffer.h>
|
||||
#include <regex.h>
|
||||
#include <modules.h>
|
||||
|
||||
static char* server_options[] = {
|
||||
"MariaDB Corporation MaxScale",
|
||||
@ -63,6 +64,9 @@ static char* server_groups[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
int config_load(char *);
|
||||
int module_create_feedback_report(GWBUF **buffer, MODULES *modules, FEEDBACK_CONF *cfg);
|
||||
int do_http_post(GWBUF *buffer, void *cfg);
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
|
@ -61,7 +61,8 @@ int result;
|
||||
dcb->fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
if(dcb->fd < 0){
|
||||
ss_dfprintf(stderr, "\nError on function call: socket() returned %d: %s\n",errno,strerror(errno));
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
ss_dfprintf(stderr, "\nError on function call: socket() returned %d: %s\n",errno,strerror_r(errno,errbuf,sizeof(errbuf)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -69,22 +69,24 @@ int setnonblocking(int fd) {
|
||||
int fl;
|
||||
|
||||
if ((fl = fcntl(fd, F_GETFL, 0)) == -1) {
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Can't GET fcntl for %i, errno = %d, %s.",
|
||||
fd,
|
||||
errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fcntl(fd, F_SETFL, fl | O_NONBLOCK) == -1) {
|
||||
char errbuf[STRERROR_BUFLEN];
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Can't SET fcntl for %i, errno = %d, %s",
|
||||
fd,
|
||||
errno,
|
||||
strerror(errno))));
|
||||
strerror_r(errno, errbuf, sizeof(errbuf)))));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user