Split off listener functionality and move SSL initiation from service to listener. Put GWPROTOCOL in its own header file.
This commit is contained in:
@ -43,7 +43,8 @@
|
||||
* 20/02/15 Markus Mäkelä Added connection_timeout parameter for services
|
||||
* 05/03/15 Massimiliano Pinto Added notification_feedback support
|
||||
* 20/04/15 Guillaume Lefranc Added available_when_donor parameter
|
||||
* 22/04/15 Martin Brampton Added disable_master_role_setting parameter
|
||||
* 22/04/15 Martin Brampton Added disable_master_role_setting parameter
|
||||
* 26/01/16 Martin Brampton Transfer SSL processing to listener
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
@ -90,6 +91,8 @@ static void global_defaults();
|
||||
static void feedback_defaults();
|
||||
static void check_config_objects(CONFIG_CONTEXT *context);
|
||||
static int maxscale_getline(char** dest, int* size, FILE* file);
|
||||
static SSL_LISTENER *make_ssl_structure(CONFIG_CONTEXT *obj);
|
||||
|
||||
int config_truth_value(char *str);
|
||||
int config_get_ifaddr(unsigned char *output);
|
||||
int config_get_release_string(char* release);
|
||||
@ -99,7 +102,7 @@ bool config_has_duplicate_sections(const char* config);
|
||||
int create_new_service(CONFIG_CONTEXT *obj);
|
||||
int create_new_server(CONFIG_CONTEXT *obj);
|
||||
int create_new_monitor(CONFIG_CONTEXT *context, CONFIG_CONTEXT *obj, HASHTABLE* monitorhash);
|
||||
int create_new_listener(CONFIG_CONTEXT *obj);
|
||||
int create_new_listener(CONFIG_CONTEXT *obj, bool startnow);
|
||||
int create_new_filter(CONFIG_CONTEXT *obj);
|
||||
int configure_new_service(CONFIG_CONTEXT *context, CONFIG_CONTEXT *obj);
|
||||
|
||||
@ -150,6 +153,13 @@ static char *listener_params[] =
|
||||
"port",
|
||||
"address",
|
||||
"socket",
|
||||
"authenticator",
|
||||
"ssl_cert",
|
||||
"ssl_ca_cert",
|
||||
"ssl",
|
||||
"ssl_key",
|
||||
"ssl_version",
|
||||
"ssl_cert_verify_depth",
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -585,7 +595,7 @@ process_config_context(CONFIG_CONTEXT *context)
|
||||
}
|
||||
else if (!strcmp(type, "listener"))
|
||||
{
|
||||
error_count += create_new_listener(obj);
|
||||
error_count += create_new_listener(obj, false);
|
||||
}
|
||||
else if (!strcmp(type, "monitor"))
|
||||
{
|
||||
@ -909,6 +919,7 @@ static struct
|
||||
{ "log_info", LOG_INFO, NULL },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
/**
|
||||
* Configuration handler for items in the global [MaxScale] section
|
||||
*
|
||||
@ -1022,6 +1033,118 @@ handle_global_item(const char *name, const char *value)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form an SSL structure from listener section parameters
|
||||
*
|
||||
* @param name The item name
|
||||
* @param value The item value
|
||||
* @return 0 on error
|
||||
*/
|
||||
static SSL_LISTENER *
|
||||
make_ssl_structure (CONFIG_CONTEXT *obj)
|
||||
{
|
||||
char *ssl, *ssl_version, *ssl_cert, *ssl_key, *ssl_ca_cert, *ssl_cert_verify_depth;
|
||||
SSL_LISTENER *new_ssl;
|
||||
int error_count = 0;
|
||||
|
||||
ssl = config_get_value(obj->parameters, "ssl");
|
||||
if (ssl && !strcmp(ssl, "required"))
|
||||
{
|
||||
if ((new_ssl = malloc(sizeof(SSL_LISTENER))) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
new_ssl->ssl_method_type = SERVICE_SSL_TLS_MAX;
|
||||
ssl_cert = config_get_value(obj->parameters, "ssl_cert");
|
||||
ssl_key = config_get_value(obj->parameters, "ssl_key");
|
||||
ssl_ca_cert = config_get_value(obj->parameters, "ssl_ca_cert");
|
||||
ssl_version = config_get_value(obj->parameters, "ssl_version");
|
||||
ssl_cert_verify_depth = config_get_value(obj->parameters, "ssl_cert_verify_depth");
|
||||
new_ssl->ssl_init_done = false;
|
||||
|
||||
if (ssl_version)
|
||||
{
|
||||
if (listener_set_ssl_version(new_ssl, ssl_version) != 0)
|
||||
{
|
||||
MXS_ERROR("Unknown parameter value for 'ssl_version' for"
|
||||
" service '%s': %s", obj->object, ssl_version);
|
||||
error_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssl_cert_verify_depth)
|
||||
{
|
||||
new_ssl->ssl_cert_verify_depth = atoi(ssl_cert_verify_depth);
|
||||
if (new_ssl->ssl_cert_verify_depth < 0)
|
||||
{
|
||||
MXS_ERROR("Invalid parameter value for 'ssl_cert_verify_depth"
|
||||
" for service '%s': %s", obj->object, ssl_cert_verify_depth);
|
||||
new_ssl->ssl_cert_verify_depth = 0;
|
||||
error_count++;
|
||||
}
|
||||
}
|
||||
|
||||
listener_set_certificates(new_ssl, ssl_cert, ssl_key, ssl_ca_cert);
|
||||
|
||||
if (new_ssl->ssl_cert == NULL)
|
||||
{
|
||||
error_count++;
|
||||
MXS_ERROR("Server certificate missing for service '%s'."
|
||||
"Please provide the path to the server certificate by adding "
|
||||
"the ssl_cert=<path> parameter", obj->object);
|
||||
}
|
||||
|
||||
if (new_ssl->ssl_ca_cert == NULL)
|
||||
{
|
||||
error_count++;
|
||||
MXS_ERROR("CA Certificate missing for service '%s'."
|
||||
"Please provide the path to the certificate authority "
|
||||
"certificate by adding the ssl_ca_cert=<path> parameter",
|
||||
obj->object);
|
||||
}
|
||||
|
||||
if (new_ssl->ssl_key == NULL)
|
||||
{
|
||||
error_count++;
|
||||
MXS_ERROR("Server private key missing for service '%s'. "
|
||||
"Please provide the path to the server certificate key by "
|
||||
"adding the ssl_key=<path> parameter",
|
||||
obj->object);
|
||||
}
|
||||
|
||||
if (access(new_ssl->ssl_ca_cert, F_OK) != 0)
|
||||
{
|
||||
MXS_ERROR("Certificate authority file for service '%s' not found: %s",
|
||||
obj->object,
|
||||
new_ssl->ssl_ca_cert);
|
||||
error_count++;
|
||||
}
|
||||
|
||||
if (access(new_ssl->ssl_cert, F_OK) != 0)
|
||||
{
|
||||
MXS_ERROR("Server certificate file for service '%s' not found: %s",
|
||||
obj->object,
|
||||
new_ssl->ssl_cert);
|
||||
error_count++;
|
||||
}
|
||||
|
||||
if (access(new_ssl->ssl_key, F_OK) != 0)
|
||||
{
|
||||
MXS_ERROR("Server private key file for service '%s' not found: %s",
|
||||
obj->object,
|
||||
new_ssl->ssl_key);
|
||||
error_count++;
|
||||
}
|
||||
|
||||
if (error_count == 0)
|
||||
{
|
||||
return new_ssl;
|
||||
}
|
||||
free(new_ssl);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration handler for items in the feedback [feedback] section
|
||||
*
|
||||
@ -1386,52 +1509,7 @@ process_config_update(CONFIG_CONTEXT *context)
|
||||
}
|
||||
else if (!strcmp(type, "listener"))
|
||||
{
|
||||
char *service;
|
||||
char *port;
|
||||
char *protocol;
|
||||
char *address;
|
||||
char *socket;
|
||||
|
||||
service = config_get_value(obj->parameters, "service");
|
||||
address = config_get_value(obj->parameters, "address");
|
||||
port = config_get_value(obj->parameters, "port");
|
||||
protocol = config_get_value(obj->parameters, "protocol");
|
||||
socket = config_get_value(obj->parameters, "socket");
|
||||
|
||||
if (service && socket && protocol)
|
||||
{
|
||||
CONFIG_CONTEXT *ptr = context;
|
||||
while (ptr && strcmp(ptr->object, service) != 0)
|
||||
{
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
if (ptr &&
|
||||
ptr->element &&
|
||||
serviceHasProtocol(ptr->element, protocol, 0) == 0)
|
||||
{
|
||||
serviceAddProtocol(ptr->element, protocol, socket, 0);
|
||||
serviceStartProtocol(ptr->element, protocol, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (service && port && protocol)
|
||||
{
|
||||
CONFIG_CONTEXT *ptr = context;
|
||||
|
||||
while (ptr && strcmp(ptr->object, service) != 0)
|
||||
{
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
if (ptr &&
|
||||
ptr->element &&
|
||||
serviceHasProtocol(ptr->element, protocol, atoi(port)) == 0)
|
||||
{
|
||||
serviceAddProtocol(ptr->element, protocol, address, atoi(port));
|
||||
serviceStartProtocol(ptr->element, protocol, atoi(port));
|
||||
}
|
||||
}
|
||||
create_new_listener(obj, true);
|
||||
}
|
||||
else if (strcmp(type, "server") != 0 &&
|
||||
strcmp(type, "monitor") != 0 &&
|
||||
@ -2633,9 +2711,10 @@ int create_new_monitor(CONFIG_CONTEXT *context, CONFIG_CONTEXT *obj, HASHTABLE*
|
||||
/**
|
||||
* Create a new listener for a service
|
||||
* @param obj Listener configuration context
|
||||
* @param startnow If true, start the listener now
|
||||
* @return Number of errors
|
||||
*/
|
||||
int create_new_listener(CONFIG_CONTEXT *obj)
|
||||
int create_new_listener(CONFIG_CONTEXT *obj, bool startnow)
|
||||
{
|
||||
int error_count = 0;
|
||||
char *service_name = config_get_value(obj->parameters, "service");
|
||||
@ -2643,20 +2722,52 @@ int create_new_listener(CONFIG_CONTEXT *obj)
|
||||
char *address = config_get_value(obj->parameters, "address");
|
||||
char *protocol = config_get_value(obj->parameters, "protocol");
|
||||
char *socket = config_get_value(obj->parameters, "socket");
|
||||
char *authenticator = config_get_value(obj->parameters, "authenticator");
|
||||
|
||||
if (service_name && protocol && (socket || port))
|
||||
{
|
||||
SERVICE *service = service_find(service_name);
|
||||
if (service)
|
||||
{
|
||||
SSL_LISTENER *ssl_info = make_ssl_structure(obj);
|
||||
if (socket)
|
||||
{
|
||||
serviceAddProtocol(service, protocol, socket, 0);
|
||||
if (serviceHasProtocol(service, protocol, 0))
|
||||
{
|
||||
MXS_ERROR("Listener '%s', for service '%s', socket %s, already have socket.",
|
||||
obj->object,
|
||||
service_name,
|
||||
socket);
|
||||
error_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
serviceAddProtocol(service, protocol, socket, 0, authenticator, ssl_info);
|
||||
if (startnow)
|
||||
{
|
||||
serviceStartProtocol(service, protocol, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (port)
|
||||
{
|
||||
serviceAddProtocol(service, protocol, address, atoi(port));
|
||||
if (serviceHasProtocol(service, protocol, atoi(port)))
|
||||
{
|
||||
MXS_ERROR("Listener '%s', for service '%s', already have port %s.",
|
||||
obj->object,
|
||||
service_name,
|
||||
port);
|
||||
error_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
serviceAddProtocol(service, protocol, address, atoi(port), authenticator, ssl_info);
|
||||
if (startnow)
|
||||
{
|
||||
serviceStartProtocol(service, protocol, atoi(port));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user