Reindent server/core/service.c

This commit is contained in:
Johan Wikman
2015-11-30 19:36:44 +02:00
parent ed06d4f14c
commit 8601068dc2
2 changed files with 1540 additions and 1410 deletions

View File

@ -27,7 +27,8 @@
* 24/06/13 Massimiliano Pinto Added: Loading users from mysql backend in serviceStart * 24/06/13 Massimiliano Pinto Added: Loading users from mysql backend in serviceStart
* 06/02/14 Massimiliano Pinto Added: serviceEnableRootUser routine * 06/02/14 Massimiliano Pinto Added: serviceEnableRootUser routine
* 25/02/14 Massimiliano Pinto Added: service refresh limit feature * 25/02/14 Massimiliano Pinto Added: service refresh limit feature
* 28/02/14 Massimiliano Pinto users_alloc moved from service_alloc to serviceStartPort (generic hashable for services) * 28/02/14 Massimiliano Pinto users_alloc moved from service_alloc to
* serviceStartPort (generic hashable for services)
* 07/05/14 Massimiliano Pinto Added: version_string initialized to NULL * 07/05/14 Massimiliano Pinto Added: version_string initialized to NULL
* 23/05/14 Mark Riddoch Addition of service validation call * 23/05/14 Mark Riddoch Addition of service validation call
* 29/05/14 Mark Riddoch Filter API implementation * 29/05/14 Mark Riddoch Filter API implementation
@ -70,18 +71,21 @@ static RSA *rsa_512 = NULL;
static RSA *rsa_1024 = NULL; static RSA *rsa_1024 = NULL;
/** To be used with configuration type checks */ /** To be used with configuration type checks */
typedef struct typelib_st { typedef struct typelib_st
{
int tl_nelems; int tl_nelems;
const char* tl_name; const char* tl_name;
const char** tl_p_elems; const char** tl_p_elems;
} typelib_t; } typelib_t;
/** Set of subsequent false,true pairs */ /** Set of subsequent false,true pairs */
static const char* bool_strings[11] = {"FALSE", "TRUE", "OFF", "ON", "N", "Y", "0", "1", "NO", "YES", 0}; static const char* bool_strings[11] = {"FALSE", "TRUE", "OFF", "ON", "N", "Y", "0", "1", "NO", "YES", 0};
typelib_t bool_type = {array_nelems(bool_strings)-1, "bool_type", bool_strings}; typelib_t bool_type = {array_nelems(bool_strings)-1, "bool_type", bool_strings};
/** List of valid values */ /** List of valid values */
static const char* sqlvar_target_strings[4] = {"MASTER", "ALL", 0}; static const char* sqlvar_target_strings[4] = {"MASTER", "ALL", 0};
typelib_t sqlvar_target_type = { typelib_t sqlvar_target_type =
{
array_nelems(sqlvar_target_strings) - 1, array_nelems(sqlvar_target_strings) - 1,
"sqlvar_target_type", "sqlvar_target_type",
sqlvar_target_strings sqlvar_target_strings
@ -92,8 +96,7 @@ static SERVICE *allServices = NULL;
static int find_type(typelib_t* tl, const char* needle, int maxlen); static int find_type(typelib_t* tl, const char* needle, int maxlen);
static void service_add_qualified_param( static void service_add_qualified_param(SERVICE* svc,
SERVICE* svc,
CONFIG_PARAMETER* param); CONFIG_PARAMETER* param);
void service_interal_restart(void *data); void service_interal_restart(void *data);
@ -112,7 +115,9 @@ service_alloc(const char *servname, const char *router)
SERVICE *service; SERVICE *service;
if ((service = (SERVICE *)calloc(1, sizeof(SERVICE))) == NULL) if ((service = (SERVICE *)calloc(1, sizeof(SERVICE))) == NULL)
{
return NULL; return NULL;
}
if ((service->router = load_module(router, MODULE_ROUTER)) == NULL) if ((service->router = load_module(router, MODULE_ROUTER)) == NULL)
{ {
char* home = get_libdir(); char* home = get_libdir();
@ -149,7 +154,9 @@ SERVICE *service;
if (service->name == NULL || service->routerModule == NULL) if (service->name == NULL || service->routerModule == NULL)
{ {
if (service->name) if (service->name)
{
free(service->name); free(service->name);
}
free(service); free(service);
return NULL; return NULL;
} }
@ -216,10 +223,12 @@ GWPROTOCOL *funcs;
goto retblock; goto retblock;
} }
if (strcmp(port->protocol, "MySQLClient") == 0) { if (strcmp(port->protocol, "MySQLClient") == 0)
{
int loaded; int loaded;
if (service->users == NULL) { if (service->users == NULL)
{
/* /*
* Allocate specific data for MySQL users * Allocate specific data for MySQL users
* including hosts and db names * including hosts and db names
@ -323,14 +332,14 @@ GWPROTOCOL *funcs;
} }
else else
{ {
if (service->users == NULL) { if (service->users == NULL)
{
/* Generic users table */ /* Generic users table */
service->users = users_alloc(); service->users = users_alloc();
} }
} }
if ((funcs=(GWPROTOCOL *)load_module(port->protocol, MODULE_PROTOCOL)) if ((funcs=(GWPROTOCOL *)load_module(port->protocol, MODULE_PROTOCOL)) == NULL)
== NULL)
{ {
users_free(service->users); users_free(service->users);
service->users = NULL; service->users = NULL;
@ -346,9 +355,13 @@ GWPROTOCOL *funcs;
memcpy(&(port->listener->func), funcs, sizeof(GWPROTOCOL)); memcpy(&(port->listener->func), funcs, sizeof(GWPROTOCOL));
if (port->address) if (port->address)
{
sprintf(config_bind, "%s:%d", port->address, port->port); sprintf(config_bind, "%s:%d", port->address, port->port);
}
else else
{
sprintf(config_bind, "0.0.0.0:%d", port->port); sprintf(config_bind, "0.0.0.0:%d", port->port);
}
if (port->listener->func.listen(port->listener, config_bind)) if (port->listener->func.listen(port->listener, config_bind))
{ {
@ -448,7 +461,6 @@ serviceStart(SERVICE *service)
{ {
int listeners = 0; int listeners = 0;
if (check_service_permissions(service)) if (check_service_permissions(service))
{ {
if (service->ssl_mode == SSL_DISABLED || if (service->ssl_mode == SSL_DISABLED ||
@ -497,7 +509,9 @@ SERV_PROTOCOL *ptr;
while (ptr) while (ptr)
{ {
if (strcmp(ptr->protocol, protocol) == 0 && ptr->port == port) if (strcmp(ptr->protocol, protocol) == 0 && ptr->port == port)
{
serviceStartPort(service, ptr); serviceStartPort(service, ptr);
}
ptr = ptr->next; ptr = ptr->next;
} }
} }
@ -548,8 +562,7 @@ int listeners = 0;
port = service->ports; port = service->ports;
while (port) while (port)
{ {
if(port->listener && if (port->listener && port->listener->session->state == SESSION_STATE_LISTENER)
port->listener->session->state == SESSION_STATE_LISTENER)
{ {
if (poll_remove_dcb(port->listener) == 0) if (poll_remove_dcb(port->listener) == 0)
{ {
@ -581,8 +594,7 @@ int listeners = 0;
port = service->ports; port = service->ports;
while (port) while (port)
{ {
if(port->listener && if (port->listener && port->listener->session->state == SESSION_STATE_LISTENER_STOPPED)
port->listener->session->state == SESSION_STATE_LISTENER_STOPPED)
{ {
if (poll_add_dcb(port->listener) == 0) if (poll_add_dcb(port->listener) == 0)
{ {
@ -609,7 +621,9 @@ service_free(SERVICE *service)
SERVICE *ptr; SERVICE *ptr;
SERVER_REF *srv; SERVER_REF *srv;
if (service->stats.n_current) if (service->stats.n_current)
{
return 0; return 0;
}
/* First of all remove from the linked list */ /* First of all remove from the linked list */
spinlock_acquire(&service_spin); spinlock_acquire(&service_spin);
if (allServices == service) if (allServices == service)
@ -624,13 +638,15 @@ SERVER_REF *srv;
ptr = ptr->next; ptr = ptr->next;
} }
if (ptr) if (ptr)
{
ptr->next = service->next; ptr->next = service->next;
} }
}
spinlock_release(&service_spin); spinlock_release(&service_spin);
/* Clean up session and free the memory */ /* Clean up session and free the memory */
while (service->dbref)
while(service->dbref){ {
srv = service->dbref; srv = service->dbref;
service->dbref = service->dbref->next; service->dbref = service->dbref->next;
free(srv); free(srv);
@ -639,9 +655,13 @@ SERVER_REF *srv;
free(service->name); free(service->name);
free(service->routerModule); free(service->routerModule);
if (service->credentials.name) if (service->credentials.name)
{
free(service->credentials.name); free(service->credentials.name);
}
if (service->credentials.authdata) if (service->credentials.authdata)
{
free(service->credentials.authdata); free(service->credentials.authdata);
}
free(service); free(service);
return 1; return 1;
} }
@ -667,9 +687,13 @@ SERV_PROTOCOL *proto;
proto->listener = NULL; proto->listener = NULL;
proto->protocol = strdup(protocol); proto->protocol = strdup(protocol);
if (address) if (address)
{
proto->address = strdup(address); proto->address = strdup(address);
}
else else
{
proto->address = NULL; proto->address = NULL;
}
proto->port = port; proto->port = port;
spinlock_acquire(&service->spin); spinlock_acquire(&service->spin);
proto->next = service->ports; proto->next = service->ports;
@ -697,7 +721,9 @@ SERV_PROTOCOL *proto;
while (proto) while (proto)
{ {
if (strcmp(proto->protocol, protocol) == 0 && proto->port == port) if (strcmp(proto->protocol, protocol) == 0 && proto->port == port)
{
break; break;
}
proto = proto->next; proto = proto->next;
} }
spinlock_release(&service->spin); spinlock_release(&service->spin);
@ -740,7 +766,9 @@ SERVER_REF *ptr;
spinlock_acquire(&service->spin); spinlock_acquire(&service->spin);
ptr = service->dbref; ptr = service->dbref;
while (ptr && ptr->server != server) while (ptr && ptr->server != server)
{
ptr = ptr->next; ptr = ptr->next;
}
spinlock_release(&service->spin); spinlock_release(&service->spin);
return ptr != NULL; return ptr != NULL;
@ -767,7 +795,9 @@ int i;
else else
{ {
for (i = 0; service->routerOptions[i]; i++) for (i = 0; service->routerOptions[i]; i++)
{
; ;
}
service->routerOptions = (char **)realloc(service->routerOptions, service->routerOptions = (char **)realloc(service->routerOptions,
(i + 2) * sizeof(char *)); (i + 2) * sizeof(char *));
service->routerOptions[i] = strdup(option); service->routerOptions[i] = strdup(option);
@ -790,7 +820,9 @@ int i;
if (service->routerOptions != NULL) if (service->routerOptions != NULL)
{ {
for (i = 0; service->routerOptions[i]; i++) for (i = 0; service->routerOptions[i]; i++)
{
free(service->routerOptions[i]); free(service->routerOptions[i]);
}
free(service->routerOptions); free(service->routerOptions);
service->routerOptions = NULL; service->routerOptions = NULL;
} }
@ -809,14 +841,20 @@ int
serviceSetUser(SERVICE *service, char *user, char *auth) serviceSetUser(SERVICE *service, char *user, char *auth)
{ {
if (service->credentials.name) if (service->credentials.name)
{
free(service->credentials.name); free(service->credentials.name);
}
if (service->credentials.authdata) if (service->credentials.authdata)
{
free(service->credentials.authdata); free(service->credentials.authdata);
}
service->credentials.name = strdup(user); service->credentials.name = strdup(user);
service->credentials.authdata = strdup(auth); service->credentials.authdata = strdup(auth);
if (service->credentials.name == NULL || service->credentials.authdata == NULL) if (service->credentials.name == NULL || service->credentials.authdata == NULL)
{
return 0; return 0;
}
return 1; return 1;
} }
@ -834,7 +872,9 @@ int
serviceGetUser(SERVICE *service, char **user, char **auth) serviceGetUser(SERVICE *service, char **user, char **auth)
{ {
if (service->credentials.name == NULL || service->credentials.authdata == NULL) if (service->credentials.name == NULL || service->credentials.authdata == NULL)
{
return 0; return 0;
}
*user = service->credentials.name; *user = service->credentials.name;
*auth = service->credentials.authdata; *auth = service->credentials.authdata;
return 1; return 1;
@ -853,7 +893,9 @@ int
serviceEnableRootUser(SERVICE *service, int action) serviceEnableRootUser(SERVICE *service, int action)
{ {
if (action != 0 && action != 1) if (action != 0 && action != 1)
{
return 0; return 0;
}
service->enable_root = action; service->enable_root = action;
@ -872,7 +914,9 @@ int
serviceAuthAllServers(SERVICE *service, int action) serviceAuthAllServers(SERVICE *service, int action)
{ {
if (action != 0 && action != 1) if (action != 0 && action != 1)
{
return 0; return 0;
}
service->users_from_all = action; service->users_from_all = action;
@ -891,7 +935,9 @@ int
serviceOptimizeWildcard(SERVICE *service, int action) serviceOptimizeWildcard(SERVICE *service, int action)
{ {
if (action != 0 && action != 1) if (action != 0 && action != 1)
{
return 0; return 0;
}
service->optimize_wildcard = action; service->optimize_wildcard = action;
if (action) if (action)
@ -913,15 +959,21 @@ void
serviceSetCertificates(SERVICE *service, char* cert,char* key, char* ca_cert) serviceSetCertificates(SERVICE *service, char* cert,char* key, char* ca_cert)
{ {
if (service->ssl_cert) if (service->ssl_cert)
{
free(service->ssl_cert); free(service->ssl_cert);
}
service->ssl_cert = strdup(cert); service->ssl_cert = strdup(cert);
if (service->ssl_key) if (service->ssl_key)
{
free(service->ssl_key); free(service->ssl_key);
}
service->ssl_key = strdup(key); service->ssl_key = strdup(key);
if (service->ssl_ca_cert) if (service->ssl_ca_cert)
{
free(service->ssl_ca_cert); free(service->ssl_ca_cert);
}
service->ssl_ca_cert = strdup(ca_cert); service->ssl_ca_cert = strdup(ca_cert);
} }
@ -935,18 +987,31 @@ int
serviceSetSSLVersion(SERVICE *service, char* version) serviceSetSSLVersion(SERVICE *service, char* version)
{ {
if (strcasecmp(version,"SSLV3") == 0) if (strcasecmp(version,"SSLV3") == 0)
{
service->ssl_method_type = SERVICE_SSLV3; service->ssl_method_type = SERVICE_SSLV3;
}
else if (strcasecmp(version,"TLSV10") == 0) else if (strcasecmp(version,"TLSV10") == 0)
{
service->ssl_method_type = SERVICE_TLS10; service->ssl_method_type = SERVICE_TLS10;
}
#ifdef OPENSSL_1_0 #ifdef OPENSSL_1_0
else if (strcasecmp(version,"TLSV11") == 0) else if (strcasecmp(version,"TLSV11") == 0)
{
service->ssl_method_type = SERVICE_TLS11; service->ssl_method_type = SERVICE_TLS11;
}
else if (strcasecmp(version,"TLSV12") == 0) else if (strcasecmp(version,"TLSV12") == 0)
{
service->ssl_method_type = SERVICE_TLS12; service->ssl_method_type = SERVICE_TLS12;
}
#endif #endif
else if (strcasecmp(version,"MAX") == 0) else if (strcasecmp(version,"MAX") == 0)
{
service->ssl_method_type = SERVICE_SSL_TLS_MAX; service->ssl_method_type = SERVICE_SSL_TLS_MAX;
else return -1; }
else
{
return -1;
}
return 0; return 0;
} }
@ -960,7 +1025,9 @@ serviceSetSSLVersion(SERVICE *service, char* version)
int serviceSetSSLVerifyDepth(SERVICE* service, int depth) int serviceSetSSLVerifyDepth(SERVICE* service, int depth)
{ {
if (depth < 0) if (depth < 0)
{
return -1; return -1;
}
service->ssl_cert_verify_depth = depth; service->ssl_cert_verify_depth = depth;
return 0; return 0;
@ -983,13 +1050,21 @@ serviceSetSSL(SERVICE *service, char* action)
int rval = 0; int rval = 0;
if (strcasecmp(action,"required") == 0) if (strcasecmp(action,"required") == 0)
{
service->ssl_mode = SSL_REQUIRED; service->ssl_mode = SSL_REQUIRED;
}
else if (strcasecmp(action,"enabled") == 0) else if (strcasecmp(action,"enabled") == 0)
{
service->ssl_mode = SSL_ENABLED; service->ssl_mode = SSL_ENABLED;
}
else if (strcasecmp(action,"disabled") == 0) else if (strcasecmp(action,"disabled") == 0)
{
service->ssl_mode = SSL_DISABLED; service->ssl_mode = SSL_DISABLED;
}
else else
{
rval = -1; rval = -1;
}
return rval; return rval;
} }
@ -1004,7 +1079,9 @@ serviceSetSSL(SERVICE *service, char* action)
int serviceStripDbEsc(SERVICE* service, int action) int serviceStripDbEsc(SERVICE* service, int action)
{ {
if (action != 0 && action != 1) if (action != 0 && action != 1)
{
return 0; return 0;
}
service->strip_db_esc = action; service->strip_db_esc = action;
@ -1023,7 +1100,9 @@ serviceSetTimeout(SERVICE *service, int val)
{ {
if (val < 0) if (val < 0)
{
return 0; return 0;
}
service->conn_timeout = val; service->conn_timeout = val;
return 1; return 1;
@ -1054,12 +1133,16 @@ trim(char *str)
char *ptr; char *ptr;
while (isspace(*str)) while (isspace(*str))
{
str++; str++;
}
/* Point to last character of the string */ /* Point to last character of the string */
ptr = str + strlen(str) - 1; ptr = str + strlen(str) - 1;
while (ptr > str && isspace(*ptr)) while (ptr > str && isspace(*ptr))
{
*ptr-- = 0; *ptr-- = 0;
}
return str; return str;
} }
@ -1150,7 +1233,9 @@ SERVICE *service;
spinlock_acquire(&service_spin); spinlock_acquire(&service_spin);
service = allServices; service = allServices;
while (service && strcmp(service->name, servname) != 0) while (service && strcmp(service->name, servname) != 0)
{
service = service->next; service = service->next;
}
spinlock_release(&service_spin); spinlock_release(&service_spin);
return service; return service;
@ -1172,7 +1257,8 @@ int i;
printf("Service %p\n", (void *)service); printf("Service %p\n", (void *)service);
printf("\tService: %s\n", service->name); printf("\tService: %s\n", service->name);
printf("\tRouter: %s (%p)\n", service->routerModule, (void *)service->router); printf("\tRouter: %s (%p)\n",
service->routerModule, (void *)service->router);
printf("\tStarted: %s", printf("\tStarted: %s",
asctime_r(localtime_r(&service->stats.started, &result), time_buf)); asctime_r(localtime_r(&service->stats.started, &result), time_buf));
printf("\tBackend databases\n"); printf("\tBackend databases\n");
@ -1297,8 +1383,10 @@ int i;
server = server->next; server = server->next;
} }
if (service->weightby) if (service->weightby)
{
dcb_printf(dcb, "\tRouting weight parameter: %s\n", dcb_printf(dcb, "\tRouting weight parameter: %s\n",
service->weightby); service->weightby);
}
dcb_printf(dcb, "\tUsers data: %p\n", dcb_printf(dcb, "\tUsers data: %p\n",
service->users); service->users);
dcb_printf(dcb, "\tTotal connections: %d\n", dcb_printf(dcb, "\tTotal connections: %d\n",
@ -1338,7 +1426,9 @@ SERVICE *service;
service = service->next; service = service->next;
} }
if (allServices) if (allServices)
{
dcb_printf(dcb, "--------------------------+----------------------+--------+---------------\n\n"); dcb_printf(dcb, "--------------------------+----------------------+--------+---------------\n\n");
}
spinlock_release(&service_spin); spinlock_release(&service_spin);
} }
@ -1375,15 +1465,16 @@ SERV_PROTOCOL *lptr;
(!lptr->listener || (!lptr->listener ||
!lptr->listener->session || !lptr->listener->session ||
lptr->listener->session->state == SESSION_STATE_LISTENER_STOPPED) ? lptr->listener->session->state == SESSION_STATE_LISTENER_STOPPED) ?
"Stopped" : "Running" "Stopped" : "Running");
);
lptr = lptr->next; lptr = lptr->next;
} }
service = service->next; service = service->next;
} }
if (allServices) if (allServices)
{
dcb_printf(dcb, "---------------------+--------------------+-----------------+-------+--------\n\n"); dcb_printf(dcb, "---------------------+--------------------+-----------------+-------+--------\n\n");
}
spinlock_release(&service_spin); spinlock_release(&service_spin);
} }
@ -1436,10 +1527,12 @@ void *router_obj;
* @param service Service to reload * @param service Service to reload
* @return 0 on success and 1 on error * @return 0 on success and 1 on error
*/ */
int service_refresh_users(SERVICE *service) { int service_refresh_users(SERVICE *service)
{
int ret = 1; int ret = 1;
/* check for another running getUsers request */ /* check for another running getUsers request */
if (! spinlock_acquire_nowait(&service->users_table_spin)) { if (!spinlock_acquire_nowait(&service->users_table_spin))
{
MXS_DEBUG("%s: [service_refresh_users] failed to get get lock for " MXS_DEBUG("%s: [service_refresh_users] failed to get get lock for "
"loading new users' table: another thread is loading users", "loading new users' table: another thread is loading users",
service->name); service->name);
@ -1447,9 +1540,10 @@ int service_refresh_users(SERVICE *service) {
return 1; return 1;
} }
/* check if refresh rate limit has exceeded */ /* check if refresh rate limit has exceeded */
if ( (time(NULL) < (service->rate_limit.last + USERS_REFRESH_TIME)) || (service->rate_limit.nloads > USERS_REFRESH_MAX_PER_TIME)) { if ((time(NULL) < (service->rate_limit.last + USERS_REFRESH_TIME)) ||
(service->rate_limit.nloads > USERS_REFRESH_MAX_PER_TIME))
{
spinlock_release(&service->users_table_spin); spinlock_release(&service->users_table_spin);
MXS_ERROR("%s: Refresh rate limit exceeded for load of users' table.", MXS_ERROR("%s: Refresh rate limit exceeded for load of users' table.",
service->name); service->name);
@ -1460,7 +1554,8 @@ int service_refresh_users(SERVICE *service) {
service->rate_limit.nloads++; service->rate_limit.nloads++;
/* update time and counter */ /* update time and counter */
if (service->rate_limit.nloads > USERS_REFRESH_MAX_PER_TIME) { if (service->rate_limit.nloads > USERS_REFRESH_MAX_PER_TIME)
{
service->rate_limit.nloads = 1; service->rate_limit.nloads = 1;
service->rate_limit.last = time(NULL); service->rate_limit.last = time(NULL);
} }
@ -1471,13 +1566,16 @@ int service_refresh_users(SERVICE *service) {
spinlock_release(&service->users_table_spin); spinlock_release(&service->users_table_spin);
if (ret >= 0) if (ret >= 0)
{
return 0; return 0;
}
else else
{
return 1; return 1;
} }
}
bool service_set_param_value ( bool service_set_param_value(SERVICE* service,
SERVICE* service,
CONFIG_PARAMETER* param, CONFIG_PARAMETER* param,
char* valstr, char* valstr,
count_spec_t count_spec, count_spec_t count_spec,
@ -1496,7 +1594,10 @@ bool service_set_param_value (
*/ */
p = valstr; p = valstr;
while(isdigit(*p)) p++; while (isdigit(*p))
{
p++;
}
errno = 0; errno = 0;
@ -1567,9 +1668,7 @@ bool service_set_param_value (
valbool = true; valbool = true;
} }
/** add param to config */ /** add param to config */
config_set_qualified_param(param, config_set_qualified_param(param, (void *)&valbool, BOOL_TYPE);
(void *)&valbool,
BOOL_TYPE);
} }
else else
{ {
@ -1594,9 +1693,7 @@ bool service_set_param_value (
valtarget = TYPE_ALL; valtarget = TYPE_ALL;
} }
/** add param to config */ /** add param to config */
config_set_qualified_param(param, config_set_qualified_param(param, (void *)&valtarget, SQLVAR_TARGET_TYPE);
(void *)&valtarget,
SQLVAR_TARGET_TYPE);
} }
else else
{ {
@ -1625,8 +1722,7 @@ bool service_set_param_value (
* 0 error * 0 error
* > 0 position in TYPELIB->type_names +1 * > 0 position in TYPELIB->type_names +1
*/ */
static int find_type( static int find_type(typelib_t* tl,
typelib_t* tl,
const char* needle, const char* needle,
int maxlen) int maxlen)
{ {
@ -1650,8 +1746,7 @@ static int find_type(
/** /**
* Add qualified config parameter to SERVICE struct. * Add qualified config parameter to SERVICE struct.
*/ */
static void service_add_qualified_param( static void service_add_qualified_param(SERVICE* svc,
SERVICE* svc,
CONFIG_PARAMETER* param) CONFIG_PARAMETER* param)
{ {
spinlock_acquire(&svc->spin); spinlock_acquire(&svc->spin);
@ -1729,7 +1824,9 @@ void
serviceWeightBy(SERVICE *service, char *weightby) serviceWeightBy(SERVICE *service, char *weightby)
{ {
if (service->weightby) if (service->weightby)
{
free(service->weightby); free(service->weightby);
}
service->weightby = strdup(weightby); service->weightby = strdup(weightby);
} }
@ -1757,7 +1854,9 @@ int
serviceEnableLocalhostMatchWildcardHost(SERVICE *service, int action) serviceEnableLocalhostMatchWildcardHost(SERVICE *service, int action)
{ {
if (action != 0 && action != 1) if (action != 0 && action != 1)
{
return 0; return 0;
}
service->localhost_match_wildcard_host = action; service->localhost_match_wildcard_host = action;
@ -1820,22 +1919,28 @@ SERV_PROTOCOL *lptr = NULL;
spinlock_acquire(&service_spin); spinlock_acquire(&service_spin);
service = allServices; service = allServices;
if (service) if (service)
{
lptr = service->ports; lptr = service->ports;
}
while (i < *rowno && service) while (i < *rowno && service)
{ {
lptr = service->ports; lptr = service->ports;
while (i < *rowno && lptr) while (i < *rowno && lptr)
{ {
if ((lptr = lptr->next) != NULL) if ((lptr = lptr->next) != NULL)
{
i++; i++;
} }
}
if (i < *rowno) if (i < *rowno)
{ {
service = service->next; service = service->next;
if (service && (lptr = service->ports) != NULL) if (service && (lptr = service->ports) != NULL)
{
i++; i++;
} }
} }
}
if (lptr == NULL) if (lptr == NULL)
{ {
spinlock_release(&service_spin); spinlock_release(&service_spin);
@ -1869,7 +1974,9 @@ RESULTSET *set;
int *data; int *data;
if ((data = (int *)malloc(sizeof(int))) == NULL) if ((data = (int *)malloc(sizeof(int))) == NULL)
{
return NULL; return NULL;
}
*data = 0; *data = 0;
if ((set = resultset_create(serviceListenerRowCallback, data)) == NULL) if ((set = resultset_create(serviceListenerRowCallback, data)) == NULL)
{ {
@ -1896,7 +2003,7 @@ static RESULT_ROW *
serviceRowCallback(RESULTSET *set, void *data) serviceRowCallback(RESULTSET *set, void *data)
{ {
int *rowno = (int *)data; int *rowno = (int *)data;
int i = 0;; int i = 0;
char buf[20]; char buf[20];
RESULT_ROW *row; RESULT_ROW *row;
SERVICE *service; SERVICE *service;
@ -1938,7 +2045,9 @@ RESULTSET *set;
int *data; int *data;
if ((data = (int *)malloc(sizeof(int))) == NULL) if ((data = (int *)malloc(sizeof(int))) == NULL)
{
return NULL; return NULL;
}
*data = 0; *data = 0;
if ((set = resultset_create(serviceRowCallback, data)) == NULL) if ((set = resultset_create(serviceRowCallback, data)) == NULL)
{ {
@ -1968,23 +2077,33 @@ int *data;
switch (keylength) { switch (keylength) {
case 512: case 512:
if (rsa_512) if (rsa_512)
{
rsa_tmp = rsa_512; rsa_tmp = rsa_512;
else { /* generate on the fly, should not happen in this example */ }
else
{
/* generate on the fly, should not happen in this example */
rsa_tmp = RSA_generate_key(keylength,RSA_F4,NULL,NULL); rsa_tmp = RSA_generate_key(keylength,RSA_F4,NULL,NULL);
rsa_512 = rsa_tmp; /* Remember for later reuse */ rsa_512 = rsa_tmp; /* Remember for later reuse */
} }
break; break;
case 1024: case 1024:
if (rsa_1024) if (rsa_1024)
{
rsa_tmp=rsa_1024; rsa_tmp=rsa_1024;
}
break; break;
default: default:
/* Generating a key on the fly is very costly, so use what is there */ /* Generating a key on the fly is very costly, so use what is there */
if (rsa_1024) if (rsa_1024)
{
rsa_tmp=rsa_1024; rsa_tmp=rsa_1024;
}
else else
{
rsa_tmp=rsa_512; /* Use at least a shorter key */ rsa_tmp=rsa_512; /* Use at least a shorter key */
} }
}
return(rsa_tmp); return(rsa_tmp);
} }
@ -2063,29 +2182,34 @@ int serviceInitSSL(SERVICE* service)
} }
if (rsa_512 != NULL && rsa_1024 != NULL) if (rsa_512 != NULL && rsa_1024 != NULL)
{
SSL_CTX_set_tmp_rsa_callback(service->ctx,tmp_rsa_callback); SSL_CTX_set_tmp_rsa_callback(service->ctx,tmp_rsa_callback);
}
/** Load the server sertificate */ /** Load the server sertificate */
if (SSL_CTX_use_certificate_file(service->ctx, service->ssl_cert, SSL_FILETYPE_PEM) <= 0) { if (SSL_CTX_use_certificate_file(service->ctx, service->ssl_cert, SSL_FILETYPE_PEM) <= 0)
{
MXS_ERROR("Failed to set server SSL certificate."); MXS_ERROR("Failed to set server SSL certificate.");
return -1; return -1;
} }
/* Load the private-key corresponding to the server certificate */ /* Load the private-key corresponding to the server certificate */
if (SSL_CTX_use_PrivateKey_file(service->ctx, service->ssl_key, SSL_FILETYPE_PEM) <= 0) { if (SSL_CTX_use_PrivateKey_file(service->ctx, service->ssl_key, SSL_FILETYPE_PEM) <= 0)
{
MXS_ERROR("Failed to set server SSL key."); MXS_ERROR("Failed to set server SSL key.");
return -1; return -1;
} }
/* Check if the server certificate and private-key matches */ /* Check if the server certificate and private-key matches */
if (!SSL_CTX_check_private_key(service->ctx)) { if (!SSL_CTX_check_private_key(service->ctx))
{
MXS_ERROR("Server SSL certificate and key do not match."); MXS_ERROR("Server SSL certificate and key do not match.");
return -1; return -1;
} }
/* Load the RSA CA certificate into the SSL_CTX structure */ /* Load the RSA CA certificate into the SSL_CTX structure */
if (!SSL_CTX_load_verify_locations(service->ctx, service->ssl_ca_cert, NULL)) { if (!SSL_CTX_load_verify_locations(service->ctx, service->ssl_ca_cert, NULL))
{
MXS_ERROR("Failed to set Certificate Authority file."); MXS_ERROR("Failed to set Certificate Authority file.");
return -1; return -1;
} }

View File

@ -65,19 +65,20 @@ struct users;
* that should be loaded to support the client connection and the port that the * that should be loaded to support the client connection and the port that the
* protocol should use to listen for incoming client connections. * protocol should use to listen for incoming client connections.
*/ */
typedef struct servprotocol { typedef struct servprotocol
{
char *protocol; /**< Protocol module to load */ char *protocol; /**< Protocol module to load */
unsigned short port; /**< Port to listen on */ unsigned short port; /**< Port to listen on */
char *address; /**< Address to listen with */ char *address; /**< Address to listen with */
DCB *listener; /**< The DCB for the listener */ DCB *listener; /**< The DCB for the listener */
struct servprotocol struct servprotocol *next; /**< Next service protocol */
*next; /**< Next service protocol */
} SERV_PROTOCOL; } SERV_PROTOCOL;
/** /**
* The service statistics structure * The service statistics structure
*/ */
typedef struct { typedef struct
{
time_t started; /**< The time when the service was started */ time_t started; /**< The time when the service was started */
int n_failed_starts; /**< Number of times this service has failed to start */ int n_failed_starts; /**< Number of times this service has failed to start */
int n_sessions; /**< Number of sessions created on service since start */ int n_sessions; /**< Number of sessions created on service since start */
@ -90,7 +91,8 @@ typedef struct {
database and extact information such as the user table or other database and extact information such as the user table or other
database status or configuration data. database status or configuration data.
*/ */
typedef struct { typedef struct
{
char *name; /**< The user name to use to extract information */ char *name; /**< The user name to use to extract information */
char *authdata; /**< The authentication data requied */ char *authdata; /**< The authentication data requied */
} SERVICE_USER; } SERVICE_USER;
@ -99,23 +101,27 @@ typedef struct {
* The service refresh rate holds the counter and last load time_t * The service refresh rate holds the counter and last load time_t
for this service to load users data from the backend database for this service to load users data from the backend database
*/ */
typedef struct { typedef struct
{
int nloads; int nloads;
time_t last; time_t last;
} SERVICE_REFRESH_RATE; } SERVICE_REFRESH_RATE;
typedef struct server_ref_t{ typedef struct server_ref_t
{
struct server_ref_t *next; struct server_ref_t *next;
SERVER* server; SERVER* server;
}SERVER_REF; }SERVER_REF;
typedef enum { typedef enum
{
SSL_DISABLED, SSL_DISABLED,
SSL_ENABLED, SSL_ENABLED,
SSL_REQUIRED SSL_REQUIRED
} ssl_mode_t; } ssl_mode_t;
enum{ enum
{
SERVICE_SSLV3, SERVICE_SSLV3,
SERVICE_TLS10, SERVICE_TLS10,
#ifdef OPENSSL_1_0 #ifdef OPENSSL_1_0
@ -142,7 +148,8 @@ enum{
* and a set of client side protocol/port pairs used to listen for new connections * and a set of client side protocol/port pairs used to listen for new connections
* to the service. * to the service.
*/ */
typedef struct service { typedef struct service
{
char *name; /**< The service name */ char *name; /**< The service name */
int state; /**< The service state */ int state; /**< The service state */
SERV_PROTOCOL *ports; /**< Linked list of ports and protocols SERV_PROTOCOL *ports; /**< Linked list of ports and protocols
@ -150,10 +157,8 @@ typedef struct service {
*/ */
char *routerModule; /**< Name of router module to use */ char *routerModule; /**< Name of router module to use */
char **routerOptions; /**< Router specific option strings */ char **routerOptions; /**< Router specific option strings */
struct router_object struct router_object *router; /**< The router we are using */
*router; /**< The router we are using */ void *router_instance; /**< The router instance for this service */
void *router_instance;
/**< The router instance for this service */
char *version_string; /** version string for this service listeners */ char *version_string; /** version string for this service listeners */
SERVER_REF *dbref; /** server references */ SERVER_REF *dbref; /** server references */
SERVICE_USER credentials; /**< The cedentials of the service user */ SERVICE_USER credentials; /**< The cedentials of the service user */
@ -163,8 +168,7 @@ typedef struct service {
int enable_root; /**< Allow root user access */ int enable_root; /**< Allow root user access */
int localhost_match_wildcard_host; /**< Match localhost against wildcard */ int localhost_match_wildcard_host; /**< Match localhost against wildcard */
HASHTABLE *resources; /**< hastable for service resources, i.e. database names */ HASHTABLE *resources; /**< hastable for service resources, i.e. database names */
CONFIG_PARAMETER* CONFIG_PARAMETER* svc_config_param;/*< list of config params and values */
svc_config_param; /*< list of config params and values */
int svc_config_version; /*< Version number of configuration */ int svc_config_version; /*< Version number of configuration */
bool svc_do_shutdown; /*< tells the service to exit loops etc. */ bool svc_do_shutdown; /*< tells the service to exit loops etc. */
bool users_from_all; /*< Load users from one server or all of them */ bool users_from_all; /*< Load users from one server or all of them */
@ -172,10 +176,8 @@ typedef struct service {
* when querying them from the server. MySQL Workbench seems * when querying them from the server. MySQL Workbench seems
* to escape at least the underscore character. */ * to escape at least the underscore character. */
bool optimize_wildcard; /*< Convert wildcard grants to individual database grants */ bool optimize_wildcard; /*< Convert wildcard grants to individual database grants */
SPINLOCK SPINLOCK users_table_spin; /**< The spinlock for users data refresh */
users_table_spin; /**< The spinlock for users data refresh */ SERVICE_REFRESH_RATE rate_limit; /**< The refresh rate limit for users table */
SERVICE_REFRESH_RATE
rate_limit; /**< The refresh rate limit for users table */
FILTER_DEF **filters; /**< Ordered list of filters */ FILTER_DEF **filters; /**< Ordered list of filters */
int n_filters; /**< Number of filters */ int n_filters; /**< Number of filters */
int conn_timeout; /*< Session timeout in seconds */ int conn_timeout; /*< Session timeout in seconds */
@ -195,7 +197,13 @@ typedef struct service {
bool log_auth_warnings; /*< Log authentication failures and warnings */ bool log_auth_warnings; /*< Log authentication failures and warnings */
} SERVICE; } SERVICE;
typedef enum count_spec_t {COUNT_NONE=0, COUNT_ATLEAST, COUNT_EXACT, COUNT_ATMOST} count_spec_t; typedef enum count_spec_t
{
COUNT_NONE = 0,
COUNT_ATLEAST,
COUNT_EXACT,
COUNT_ATMOST
} count_spec_t;
#define SERVICE_STATE_ALLOC 1 /**< The service has been allocated */ #define SERVICE_STATE_ALLOC 1 /**< The service has been allocated */
#define SERVICE_STATE_STARTED 2 /**< The service has been started */ #define SERVICE_STATE_STARTED 2 /**< The service has been started */
@ -231,28 +239,26 @@ extern void serviceSetRetryOnFailure(SERVICE *service, char* value);
extern void serviceWeightBy(SERVICE *, char *); extern void serviceWeightBy(SERVICE *, char *);
extern char *serviceGetWeightingParameter(SERVICE *); extern char *serviceGetWeightingParameter(SERVICE *);
extern int serviceEnableLocalhostMatchWildcardHost(SERVICE *, int); extern int serviceEnableLocalhostMatchWildcardHost(SERVICE *, int);
int serviceStripDbEsc(SERVICE* service, int action); extern int serviceStripDbEsc(SERVICE* service, int action);
int serviceAuthAllServers(SERVICE *service, int action); extern int serviceAuthAllServers(SERVICE *service, int action);
int serviceOptimizeWildcard(SERVICE *service, int action); extern int serviceOptimizeWildcard(SERVICE *service, int action);
extern void service_update(SERVICE *, char *, char *, char *); extern void service_update(SERVICE *, char *, char *, char *);
extern int service_refresh_users(SERVICE *); extern int service_refresh_users(SERVICE *);
extern void printService(SERVICE *); extern void printService(SERVICE *);
extern void printAllServices(); extern void printAllServices();
extern void dprintAllServices(DCB *); extern void dprintAllServices(DCB *);
extern bool service_set_param_value(SERVICE* service,
bool service_set_param_value (
SERVICE* service,
CONFIG_PARAMETER* param, CONFIG_PARAMETER* param,
char* valstr, char* valstr,
count_spec_t count_spec, count_spec_t count_spec,
config_param_type_t type); config_param_type_t type);
extern void dprintService(DCB *, SERVICE *); extern void dprintService(DCB *, SERVICE *);
extern void dListServices(DCB *); extern void dListServices(DCB *);
extern void dListListeners(DCB *); extern void dListListeners(DCB *);
char* service_get_name(SERVICE* svc); extern char* service_get_name(SERVICE* svc);
void service_shutdown(); extern void service_shutdown();
extern int serviceSessionCountAll(); extern int serviceSessionCountAll();
extern RESULTSET *serviceGetList(); extern RESULTSET *serviceGetList();
extern RESULTSET *serviceGetListenerList(); extern RESULTSET *serviceGetListenerList();
#endif #endif